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

set CVSRevisionAuthor ""

APSApplication . -name SRbpmOffsetHistoryViewer -version $CVSRevisionAuthor \
  -overview "Review BPM offset evaluation."

proc SelectedBPMList {args} {
    global rootname
    set sectorCount 40
    set excludeP0s 0
    set excludeIDXray 1
    set excludeBMXray 1
    set excludeFPGA 0
    set electronicsType *
    set useWildcard ""
    APSParseArguments {excludeP0s excludeIDXray useWildcard excludeBMXray electronicsType excludeFPGA}
    set BPMSuffixList [list A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1]
    set excludeSuffix ""
    if !$excludeP0s {
        set BPMSuffixList [concat A:P0 $BPMSuffixList B:P0 C:P0]
    } else {
        lappend excludeSuffix A:P0 B:P0 C:P0
    }
    if !$excludeIDXray {
        set BPMSuffixList [concat $BPMSuffixList ID:P1 ID:P2]
    } else {
        lappend excludeSuffix ID:P1 ID:P2
    }
    if !$excludeBMXray {
        set BPMSuffixList [concat $BPMSuffixList BM:P1 BM:P2]
    } else {
        lappend excludeSuffix BM:P1 BM:P2
    }
    set AllowedByElectronicsList ""
    if [string compare $electronicsType *]!=0 {
        if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                     -match=column,ElectronicsType=$electronicsType \
                     | sdds2stream -pipe -column=DeviceName} AllowedByElectronicsList] {
            SetStatus "Unable to get list of BPMs with electronics $electronicsType"
            return ""
        }
    }
    if $excludeFPGA {
        global FPGAbpmList
        if ![info exist FPGAbpmList] {
            if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                         -match=column,ElectronicsType=FPGA \
                         | sdds2stream -pipe -column=DeviceName} FPGAbpmList] {
                SetStatus "Unable to get list of BPMs with electronics FPGA"
                return ""
            }
        }
    }
    set names ""
    for {set sector 1} {$sector<=$sectorCount} {incr sector} {
        foreach suffix $BPMSuffixList {
            set nameFlagx ${rootname}S${sector}${suffix}
            global $nameFlagx 
            if {$useWildcard != "" && ![string match $useWildcard $suffix]} {
              #  set $nameFlagx 0
                continue
            }           
            if [set $nameFlagx] {
                if {![llength $AllowedByElectronicsList] || \
                      [lsearch -exact $AllowedByElectronicsList S${sector}${suffix}]!=-1} {
                    if $excludeFPGA {
                        if [lsearch -exact $FPGAbpmList S${sector}${suffix}]<0 {
                            lappend names ${sector}$suffix
                        }
                    } else {
                        lappend names ${sector}$suffix
                    }
                }
            }
        }
    }
    return $names
}

proc Update {} {
    global outputDir uTimeText
    global EndDay EndMonth EndYear

    set BPMDir /home/helios/oagData/logging/srBPMAve
    set BunchDir /home/helios/oagData/monitoring/SRvac
    set ALLBPMList {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0}

    set TimeStep [expr 3600*24*30]
    set Current [clock seconds]

    for {set i 0} {$i < 100} {incr i} {
        set tmpFile /tmp/[APSTmpString]
        set fileList1 ""
        set fileList2 ""
        set StartTime [expr int([exec sdds2stream $outputDir/log.sdds -para=EndTime])]
        set EndTime [expr $StartTime+$TimeStep]
        if {$EndTime>$Current} {
            set EndTime $Current
            set i 101
        }
        set Time $StartTime
        set index 1

        while {$Time<$EndTime} {
            set Time [expr $Time+3600*24]
# use sparse=15 change data point interval from 1min to 15min. This is enough for our purpose.
            catch {exec sddsprocess $BPMDir/srBPMAve-[clock format $Time -format %Y-%j-%m%d].gz -pipe=out -noWarning \
                       -filt=col,CAerrors,0,0 -filt=col,SRDesiredMode,1,1 \
                       "-retain=col,CAerrors,Time,SRDesiredMode,*A:*OffsetAO,*B:*OffsetAO" \
                       | sddscast -pipe -cast=col,Time,double,long \
                       | sddscombine -pipe -merge \
                       | sddsprocess -pipe -sparse=15 \
                       | sddssort -pipe=in -col=Time $tmpFile-$index.bpm1
                lappend fileList2 $tmpFile-$index.bpm1
            } results
            
            catch {exec sddsprocess $BunchDir/SRvac-[clock format $Time -format %Y-%j-%m%d].gz -pipe=out -noWarning \
                       "-retain=col,Time,SRBucketsFilled" \
                       | sddscast -pipe -cast=col,Time,double,long \
                       | sddscombine -pipe -merge \
                       | sddssort -pipe -col=Time \
                       | sddsinterp -pipe=in $tmpFile-$index.bunch -fileValues=$tmpFile-$index.bpm1,col=Time \
                       -col=Time,SRBucketsFilled
                lappend fileList2 $tmpFile-$index.bunch
            }
            catch {exec sddsxref $tmpFile-$index.bpm1 $tmpFile-$index.bunch -pipe=out -noWarning \
                       -reuse=rows,page -take=SRBucketsFilled -equate=Time  \
                       | sddsprocess -pipe=in $tmpFile-$index.bpm  -noWarning \
                       "-filt=col,SRBucketsFilled,24,24,SRBucketsFilled,57,57,|,SRBucketsFilled,324,324,|" 
                lappend fileList1 $tmpFile-$index.bpm
            }
            incr index
        }
        catch {eval exec sddscombine $fileList1 -merge -pipe=out \
                   | sddssort -pipe -col=Time,inc \
                   | sddsbreak -pipe -gapin=SRBucketsFilled,amount=0.1 \
                   | sddsprocess -pipe=in $tmpFile.out} results
        catch {eval file delete -force $fileList1}
        catch {eval file delete -force $fileList2}

        if [lindex [exec sdds2stream -rows $tmpFile.out] 0] {
            for {set sector 1} {$sector<41} {incr sector} {
                foreach BPM $ALLBPMList {
                    catch {exec sddsprocess $tmpFile.out -pipe=out -del=para,* \
                               -retain=col,Time,SRBucketsFilled,S$sector$BPM:ms:x:OffsetAO \
                               | sddsbreak -pipe -changeof=S$sector$BPM:ms:x:OffsetAO,amount=1e-4 \
                               | sddsprocess -pipe -proc=Time,first,StartTime -proc=Time,last,EndTime \
                               -proc=SRBucketsFilled,first,FillPattern -proc=S$sector$BPM:ms:x:OffsetAO,first,S$sector$BPM:ms:x:OffsetAO \
                               | sddscollapse -pipe=in $tmpFile.S$sector$BPM-x2 -nowarning} results
                    if [file exists $tmpFile.S$sector$BPM-x2] {            
                        if [file exists $outputDir/S$sector$BPM-x] {
                            exec cp -f $outputDir/S$sector$BPM-x $outputDir/S$sector$BPM-x.bak
                            eval exec sddscombine $outputDir/S$sector$BPM-x.bak $tmpFile.S$sector$BPM-x2 -pipe=out -merge \
                                | sddssort -pipe -col=StartTime,inc \
                                | sddsbreak -pipe -gapin=S$sector$BPM:ms:x:OffsetAO,amount=1e-4 \
                                | sddsprocess -pipe -del=para,T0,T1 \
                                | sddsprocess -pipe -proc=StartTime,first,T0 -proc=EndTime,last,T1 \
                                "-redef=para,zero,0" "-reprint=para,BPMName,S$sector$BPM-x:%g,zero" \
                                | sddsprocess -pipe -clip=0,1,invert -del=para,zero "-reedit=para,BPMName,%/:0//"\
                                -redef=col,StartTime,T0 -redef=col,EndTime,T1 \
                                | sddscombine -pipe=in $outputDir/S$sector$BPM-x -merge -over
                        } else {
                            exec sddsbreak $tmpFile.S$sector$BPM-x2 -pipe=out \
                                -gapin=S$sector$BPM:ms:x:OffsetAO,amount=1e-4 \
                                | sddsprocess -pipe -del=para,T0,T1 \
                                | sddsprocess -pipe -proc=StartTime,first,T0 -proc=EndTime,last,T1 \
                                "-redef=para,zero,0" "-reprint=para,BPMName,S$sector$BPM-x:%g,zero" \
                                | sddsprocess -pipe -clip=0,1,invert -del=para,zero "-reedit=para,BPMName,%/:0//"\
                                -redef=col,StartTime,T0 -redef=col,EndTime,T1 \
                                | sddscombine -pipe=in $outputDir/S$sector$BPM-x -merge -over
                        }
                        catch {eval file delete -force $tmpFile.S$sector$BPM-x2}
                    }
                    
                    catch {exec sddsprocess $tmpFile.out -pipe=out -del=para,* \
                               -retain=col,Time,SRBucketsFilled,S$sector$BPM:ms:y:OffsetAO \
                               | sddsbreak -pipe -changeof=S$sector$BPM:ms:y:OffsetAO,amount=1e-4 \
                               | sddsprocess -pipe -proc=Time,first,StartTime -proc=Time,last,EndTime \
                               -proc=SRBucketsFilled,first,FillPattern -proc=S$sector$BPM:ms:y:OffsetAO,first,S$sector$BPM:ms:y:OffsetAO \
                               | sddscollapse -pipe=in $tmpFile.S$sector$BPM-y2 -nowarning} results
                    if [file exists $tmpFile.S$sector$BPM-y2] {            
                        if [file exists $outputDir/S$sector$BPM-y] {
                            exec cp -f $outputDir/S$sector$BPM-y $outputDir/S$sector$BPM-y.bak
                            eval exec sddscombine $outputDir/S$sector$BPM-y.bak $tmpFile.S$sector$BPM-y2 -pipe=out -merge \
                                | sddssort -pipe -col=StartTime,inc \
                                | sddsbreak -pipe -gapin=S$sector$BPM:ms:y:OffsetAO,amount=1e-4 \
                                | sddsprocess -pipe -del=para,T0,T1 \
                                | sddsprocess -pipe -proc=StartTime,first,T0 -proc=EndTime,last,T1 \
                                "-redef=para,zero,0" "-reprint=para,BPMName,S$sector$BPM-y:%g,zero" \
                                | sddsprocess -pipe -clip=0,1,invert -del=para,zero "-reedit=para,BPMName,%/:0//"\
                                -redef=col,StartTime,T0 -redef=col,EndTime,T1 \
                                | sddscombine -pipe=in $outputDir/S$sector$BPM-y -merge -over
                        } else {
                            exec sddsbreak $tmpFile.S$sector$BPM-y2 -pipe=out \
                                -gapin=S$sector$BPM:ms:y:OffsetAO,amount=1e-4 \
                                | sddsprocess -pipe -del=para,T0,T1 \
                                | sddsprocess -pipe -proc=StartTime,first,T0 -proc=EndTime,last,T1 \
                                "-redef=para,zero,0" "-reprint=para,BPMName,S$sector$BPM-y:%g,zero" \
                                | sddsprocess -pipe -clip=0,1,invert -del=para,zero "-reedit=para,BPMName,%/:0//"\
                                -redef=col,StartTime,T0 -redef=col,EndTime,T1 \
                                | sddscombine -pipe=in $outputDir/S$sector$BPM-y -merge -over
                        }
                        catch {eval file delete -force $tmpFile.S$sector$BPM-y2}
                    }
                }
            }
            #            catch {eval file delete -force $tmpFile.out}
        }
        exec cp -f $outputDir/log.sdds $outputDir/log.sdds.bak
        exec sddsprocess $outputDir/log.sdds -redef=para,EndTime,$EndTime,type=long -nowarning
        set uTimeText [clock format $EndTime -format %Y-%m-%d]
        set EndDay [clock format $EndTime -format %d]
        set EndMonth [clock format $EndTime -format %m]
        set EndYear [clock format $EndTime -format %Y]
        SetStatus "Done update"
    }

}

proc Plot {args} {
    set mode ""
    APSParseArguments {mode}
    
    global nBunch outputDir plane
    global StartDay StartMonth StartYear
    global EndDay EndMonth EndYear

    set t0 [clock scan $StartYear-$StartMonth-$StartDay]
    set t1 [clock scan $EndYear-$EndMonth-$EndDay]
    set BPMList [SelectedBPMList]
    set tmpFile /tmp/[APSTmpString]
    set fileList ""
    foreach BPM $BPMList {
        if [file exists $outputDir/S$BPM-$plane] {
            exec sddsprocess $outputDir/S$BPM-$plane -pipe=out -nowarning \
                "-redef=col,Offset,S$BPM:ms:$plane:OffsetAO" "-edit=para,BPM,BPMName,%/-$plane//" \
                -proc=Offset,ave,x0 -proc=Offset,standardDeviation,xstd -proc=Offset,spread,dx \
                "-reprint=para,toplabel,Ave: %g SDeV: %g Range: %g(mm),x0,xstd,dx" \
                | sddsprocess -pipe=in $tmpFile-S$BPM -del=col,*AO -nowarning  "-reedit=para,BPMName,ei/(mm)/"
            if {$nBunch} {exec sddsprocess $tmpFile-S$BPM -nowarning -filt=col,FillPattern,$nBunch,$nBunch}
            lappend fileList $tmpFile-S$BPM
        }
    }

    if [string match $mode single] {
        eval exec sddscombine $fileList $tmpFile.plot -over
        set plotOption "-thick=2 -title= -filt=col,StartTime,$t0,$t1 -filt=col,EndTime,$t0,$t1" 
        set plotOption "$plotOption -tick=xtime -ylabel=@BPMName -topl=@toplabel -split=page -separate=page -group=page" 
        if {$nBunch} {
            eval exec sddsplot [subst $plotOption] $tmpFile.plot \
                -col=StartTime,Offset -grap=sym,type=2,fill,scale=2,sub=1 -filt=col,FillPattern,$nBunch,$nBunch -leg=spec=$nBunch &
        } else {
            eval exec sddsplot [subst $plotOption] $tmpFile.plot \
                -col=StartTime,Offset -grap=sym,type=2,fill,scale=2,sub=1 -filt=col,FillPattern,24,24 -leg=spec=24 \
                -col=StartTime,Offset -grap=sym,type=2,fill,scale=2,sub=2 -filt=col,FillPattern,324,324 -leg=spec=324 \
                -col=StartTime,Offset -grap=sym,type=2,fill,scale=2,sub=3 -filt=col,FillPattern,57,57 -leg=spec=Hybrid &
        }
    }

    if [string match $mode all] {
        set plotOption1 "-grap=sym,subtype=1,con=sub,fill,type=2,thick=2,scale=1 -ys=id=1"
        set plotOption2 "-grap=sym,subtype=2,con=sub,fill,type=2,thick=2,scale=1 -ys=id=2"
        eval exec sddscombine $fileList -pipe=out \
            | sddsprocess -pipe "-redef=para,Count,n_rows" -filt=col,StartTime,$t0,$t1 -filt=col,EndTime,$t0,$t1 \
            -proc=Offset,ave,OffsetAve -proc=Offset,standardDeviation,OffsetStDev -proc=Offset,spread,OffsetRange \
            | sddscollapse -pipe \
            | sddsprocess -pipe=in $tmpFile.plot -redef=col,OffsetAve,OffsetAve,units=mm \
            -redef=col,OffsetStDev,OffsetStDev,units=mm -redef=col,OffsetRange,OffsetRange,units=mm 
        eval exec sddsplot -thick=2 -title= $tmpFile.plot -leg \
            -col=BPM,OffsetStDev [subst $plotOption1] -col=BPM,Count [subst $plotOption2] "-ylabel=Total-DataPoints" &
        eval exec sddsplot -thick=2 -title= $tmpFile.plot -leg \
            -col=BPM,OffsetAve [subst $plotOption1] -col=BPM,Count [subst $plotOption2] "-ylabel=Total-DataPoints" &
        eval exec sddsplot -thick=2 -title= $tmpFile.plot -leg \
            -col=BPM,OffsetRange [subst $plotOption1] -col=BPM,Count [subst $plotOption2] "-ylabel=Total-DataPoints" &
    }

    catch {eval file delete -force $fileList }
    SetStatus "Done plot"
}

proc setMode {args} {
    APSStrictParseArguments {mode}
    global plane rootname 
    switch $mode {
        h {
            set plane x
            set rootname hconfig
        }
        v {
            set plane y
            set rootname vconfig
        }
        default {
            return -code error "The mode has to be h or v"
        }
    }
#    SetStatus "$plane $rootname"
}

proc MakeBPMSelectionFrame {widget args} {
    set parent ""
    APSStrictParseArguments {parent}

    set widgetList [APSTabFrame .controls -parent $parent -labelList "Horizontal Vertical" \
                        -commandList {"setMode -mode h" "setMode -mode v"} -width 1110 -height 400]
    set frameh [lindex $widgetList 0]
    set framev [lindex $widgetList 1]

    APSFrame .bpmh -parent $frameh
    set w $frameh.bpmh.frame
    APSSRMonitorCheckButtons .bpmhbut -parent $w -rootname hconfig -noLabel 1 -sectorControl 1 \
        -orientation horizontal -includeP0s 1 -includeIDs 0 -includeBMs 0 

    APSFrame .bpmv -parent $framev
    set w $framev.bpmv.frame
    APSSRMonitorCheckButtons .bpmvbut -parent $w -rootname vconfig -noLabel 1 -sectorControl 1 \
        -orientation horizontal -includeP0s 1 -includeIDs 0 -includeBMs 0 
}

proc MakeParameterFrame {widget args} {
    global cTime uTime cTimeText uTimeText
    global nBunch outputDir
    global StartDay StartMonth StartYear
    global EndDay EndMonth EndYear

    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "" -packOption "-side top -fill x"
    set w $parent$widget.frame

    APSRadioButtonFrame .mode -parent $w -orientation horizontal \
        -label "Fill Pattern:" -variable nBunch \
        -buttonList {All Hybrid 24 324} \
        -valueList {0 57 24 324} -contextHelp \
        "Choose fill pattern for data review."

    set cTime [expr int([exec sdds2stream $outputDir/log.sdds -para=StartTime])]
    set uTime [expr int([exec sdds2stream $outputDir/log.sdds -para=EndTime])]
    set cTimeText [clock format $cTime -format %Y-%m-%d]
    set uTimeText [clock format $uTime -format %Y-%m-%d]
    APSLabeledOutput .start -parent $w -label "First data collection time:" -textVariable cTimeText \
        -width 19 -contextHelp "Last data collection time" 
    APSLabeledOutput .end -parent $w -label "Last data update time:" -textVariable uTimeText \
        -width 19 -contextHelp "Last data collection time"

    set StartDay [clock format $cTime -format %d]
    set StartMonth [clock format $cTime -format %m]
    set StartYear [clock format $cTime -format %Y]
    set EndDay [clock format $uTime -format %d]
    set EndMonth [clock format $uTime -format %m]
    set EndYear [clock format $uTime -format %Y]
    set label "Plot starting date/time (year, month, day): "
    APSLabeledEntryFrame .pstart -parent $w  -label $label \
        -variableList "StartYear StartMonth StartDay"  -width 6 -orientation horizontal  \
        -contextHelp "Enter the year, month, day of the plot." 
    set label "Plot ending date/time (year, month, day):   "
    APSLabeledEntryFrame .pend -parent $w  -label $label \
        -variableList "EndYear EndMonth EndDay"  -width 6 -orientation horizontal  \
        -contextHelp "Enter the year, month, day of the plot." 
}

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

    APSFrame $widget -parent $parent -label "" -packOption "-anchor w"
    set w $parent$widget.frame

    APSButton .update -parent $w -text Update -command Update -contextHelp "Update data collection from last time to today, need login to oag account." 
    APSButton .plot -parent $w -text Plot-Single -command "Plot -mode single" -contextHelp "Plot BPM offset history in 1 BPM/Page."
    APSButton .plot1 -parent $w -text Plot-Summary -command "Plot -mode all" -contextHelp "Plot summary of BPM offset history."
}

proc SetStatus {text} {
    global status
    set status "$text"
    update
}

set status "Working..."
set plane x
set rootname hconfig
set nBunch 0
set outputDir /home/helios/oagData/sr/bpmOffsets/history
#set outputDir /home/oxygen/XIAOAM/Operation/BPMtest/output1

APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 -height 4
MakeBPMSelectionFrame .bpm -parent .userFrame 
MakeParameterFrame .param -parent .userFrame
MakeActionFrame .action -parent .userFrame

update
set status "Ready."

# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
