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

set CVSRevisionAuthor "\$Revision: 1.17 $ \$Author: soliday $"

APSApplication . -name SROrbitCompare -version $CVSRevisionAuthor \
        -overview "Compares storage ring orbit data between two times."

#This is just temporary until the APSU starts
if {[llength [glob -nocomplain /home/helios/oagData/logging/srBPMAve.test/srBPMAve-[clock format [clock seconds] -format "%Y-%j"]-*]] > 0} {
    set dataDir /home/helios/oagData/logging/srBPMAve.test
} else {
    set dataDir /home/helios/oagData/logging/srBPMAve
}

set xrefDir $OAGGlobal(SRLatticesDirectory)/scripts

set dataRootname srBPMAve

#cd $dataDir

set IDP0File /tmp/[APSTmpString]
set IDP1File /tmp/[APSTmpString]
APSAddToTempFileList $IDP0File.1 $IDP0File.2 $IDP0File
APSAddToTempFileList $IDP1File.1 $IDP1File.2 $IDP1File

set BMBPMFile /tmp/[APSTmpString]
APSAddToTempFileList $BMBPMFile.1 $BMBPMFile.2 $BMBPMFile


set status "Ready."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 60 \
    -height 8 -packOption "-fill both -expand true"

proc MakeDateTimeFrame {widget args} {
    set parent .
    set rootname ""
    APSStrictParseArguments {parent rootname glitchMode}
    set label "Dates and Times of Interest"

    APSFrame $widget -parent $parent -label $label
    set w $parent$widget.frame

    APSDateTimeAdjEntry .startDate -parent $w \
      -yearVariable ${rootname}StartYear \
      -monthVariable ${rootname}StartMonth \
      -dayVariable ${rootname}StartDay \
      -hourVariable ${rootname}StartHour \
      -label "Time 1 (year, month, day, hour): " -defaultHour 0 \
      -buttonSize small

    APSDateTimeAdjEntry .endDate -parent $w \
      -yearVariable ${rootname}EndYear \
      -monthVariable ${rootname}EndMonth \
      -dayVariable ${rootname}EndDay \
      -hourVariable ${rootname}EndHour \
      -label "Time 2 (year, month, day, hour): " -defaultHour 0 \
      -buttonSize small

    global ${rootname}TimeWindow
    set ${rootname}TimeWindow 10
    APSLabeledEntry .window -parent $w \
      -textVariable ${rootname}TimeWindow \
      -label "Averaging window (minutes): " \
      -contextHelp "Enter the time in minutes over which to average data.  A value of 0 means use one sample."

    SetDateTimeToToday -rootname ${rootname}Start -hour 0
    SetDateTimeToToday -rootname ${rootname}End 
}

proc MakePlotControls {widget args} {
    set parent .
    set label ""
    APSStrictParseArguments {parent label}

    APSFrame $widget -parent $parent -label $label
    set w $parent$widget.frame
    
    global plotDataLimit plotChangeLimit
    set plotDataLimit 0
    set plotChangeLimit 0
    APSLabeledEntry .window1 -parent $w \
      -textVariable plotDataLimit -label "Data limit for plots (mm): " \
      -contextHelp "Enter the limit in mm for plots of orbit data."
    APSLabeledEntry .window2 -parent $w \
      -textVariable plotChangeLimit -label "Change limit for plots (mm): " \
      -contextHelp "Enter the limit in mm for plots of orbit changes."
    APSLabeledEntryFrame .sectorLimits -parent $w -label "Sector range for plotting:        " \
      -variableList {sectorLowerLimit sectorUpperLimit} -width 4 \
      -orientation horizontal -contextHelp \
      "Enter the first and last sector to be shown on the plots."
    APSCheckButtonFrame .cb -parent $w \
      -label "Some plot options: " \
      -orientation horizontal \
      -buttonList {"Connected symbols" "X-axes" "Use BPM names"} \
      -variableList {plotOption(ConnSym) plotOption(axes) plotOption(names)} \
      -allNone 1 -contextHelp \
      "Enter plot options."
    APSLabeledEntry .plotOptions -parent $w -label "Extra plot options: " \
      -textVariable extraPlotOptions -width 40 \
      -contextHelp \
      "Enter extra options for plot."
}

proc SetDateTimeToToday {args} {
    set rootname ""
    set hour [exec timeconvert -seconds=[expr [exec timeconvert -now | token -last]-120] | token -n=5]
    set hh [expr int($hour)]
    set mm [expr int(60*($hour-int($hour)))]
    set hour [format %02ld:%02ld $hh $mm]
    APSStrictParseArguments {rootname hour}

    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable ${rootname}Day -yearVariable ${rootname}Year \
      -monthVariable ${rootname}Month -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
}

set readbackChoice Error
set doHPlots 1
set doVPlots 1
set hScalingMode fixedAuto
set vScalingMode fixedAuto
set hUserLowerScale -0.1
set hUserUpperScale 0.1
set vUserLowerScale -0.1
set vUserUpperScale 0.1
set abscissaColumn Sector
set sectorLowerLimit 1
set sectorUpperLimit 40
set plotOption(ConnSym) 1
set plotOption(axes) 1

set processFlag(plotData) 0
set processFlag(plotChanges) 0
set processFlag(P0Comparison) 0
set processFlag(IDComparison) 0
set processFlag(BMComparison) 0
set processFlag(comparison) 0

proc MakeButtonRow {widget args} {
    set parent ""
    set packOption "-side top"
    APSStrictParseArguments {parent packOption}

    APSFrame $widget -parent $parent -label "Analysis" -packOption $packOption
    set w $parent$widget.frame
    global processFlag

    APSRadioButtonFrame .item -parent $w -label "Readback type: " \
      -buttonList {LowPass1s LowPass8s LowPass64s Unadjusted Adjusted Error Sampled SampledAdjusted Position Setpoint Offset Gain} \
      -valueList {LowPass1s LowPass8s LowPass64s Unadjusted Adjusted Error Sampled SampledAdjusted Position Setpoint Offset Gain} \
      -orientation vertical -packOption "-side left" \
      -variable readbackChoice \
      -contextHelp "Choose which type of BPM readback you want to look at.  Error is the ErrorM readback that we correct on.  Setpoint is the orbit setpoint that we steer to.  Offset is the offset of the BPM, a combination of the measured offset and the intensity compensated offset.  Unadjusted is the raw value before removing the offset.  Adjusted is the raw value with the offset removed."

    APSCheckButtonFrame .cb -parent $w \
      -label "Choices: " -packOption "-side left" -orientation vertical \
      -buttonList {"Plot Data" "Plot Changes" "Compare P0s" "Compare P1s" "Compare BMs"  "Compare All"} \
      -variableList {processFlag(plotData) processFlag(plotChanges) \
                       processFlag(P0Comparison) \
                       processFlag(IDComparison) processFlag(BMComparison) \
                       processFlag(comparison) } -allNone 1
    APSButton .go -parent $w -text Go -command DoComparisons 
}

proc FindPVDataFiles {args} {
    set ReadbackName ""
    set StartTime [clock scan "Jan 01 00:00:00 1990"]
    set EndTime [clock seconds]
    set startDateList ""
    set endDateList ""
    set SampleIntervals "1 2 4 8 16 32 64 128 256"
    APSStrictParseArguments {ReadbackName StartTime EndTime SampleIntervals startDateList endDateList}

    if {[llength $startDateList]} {
        set StartTime [clock scan "[lindex $startDateList 2]/[lindex $startDateList 3]/[lindex $startDateList 0]"]
    }
    if {[llength $endDateList]} {
        set EndTime [clock scan "23:59:59 [lindex $endDateList 2]/[lindex $endDateList 3]/[lindex $endDateList 0]"]
    }
    
    set fileList ""
    set ReadbackName [join [split $ReadbackName / ] + ]
    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]
    while {($year < $endyear) || (($year == $endyear) && ($month <= $endmonth))} {
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/Variable/[string index ${ReadbackName} 0]/${ReadbackName}/log-${year}-${month}.{gz,xz}]] "
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/\{[join $SampleIntervals ,]\}/${ReadbackName}/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]
        }
    }
    return $fileList
}

proc DoComparisons {} {
    global processFlag readbackChoice
    global dataRootname dataDir
    global StartMonth StartYear StartDay StartHour 
    global EndMonth EndYear EndDay EndHour TimeWindow
    global sectorLowerLimit sectorUpperLimit

    if [catch {APSConvertTimeToHours $StartHour} hour] {
        APSSetVarAndUpdate status "Invalid starting hour: $StartHour"
        return
    }
    set startTime \
      [exec timeconvert \
         -breakDown=year=$StartYear,day=$StartDay,month=$StartMonth,hour=$hour]

    if [catch {APSConvertTimeToHours $EndHour} hour] {
        APSSetVarAndUpdate status "Invalid ending hour: $EndHour"
        return
    }
    set endTime \
      [exec timeconvert \
         -breakDown=year=$EndYear,day=$EndDay,month=$EndMonth,hour=$hour]

    APSSetVarAndUpdate status "Working..."
    
    set datafile1 [APSFindFilesBetweenDates \
                     -rootname ${dataRootname}- \
                     -directory $dataDir \
                     -startDateList [APSFormatDate -year $StartYear -month $StartMonth \
                                       -day $StartDay -dateFormat list] \
                     -endDateList [APSFormatDate -year $StartYear -month $StartMonth \
                                     -day $StartDay -dateFormat list] ]
    if ![llength $datafile1] {
        APSSetVarAndUpdate status "No data found for time 1"
        return
    }
    
    set datafile2 [APSFindFilesBetweenDates \
                     -rootname ${dataRootname}- \
                     -directory $dataDir \
                     -startDateList [APSFormatDate -year $EndYear -month $EndMonth \
                                       -day $EndDay -dateFormat list] \
                     -endDateList [APSFormatDate -year $EndYear -month $EndMonth \
                                     -day $EndDay -dateFormat list] ]
    if ![llength $datafile2] {
        APSSetVarAndUpdate status "No data found for time 2"
        return
    }

    switch $readbackChoice {
        LowPass1s {
            set msType ""
            set readingType :LowPass1sAdjustedM
        }
        LowPass8s {
            set msType ""
            set readingType :LowPass8sAdjustedM
        }
        LowPass64s {
            set msType ""
            set readingType :LowPass64sAdjustedM
        }
        Sampled {
            set msType ""
            set readingType :SampledM
        }
        SampledAdjusted {
            set msType ""
            set readingType :SampledAdjustedM
        }
        Position {
            set msType ""
            set readingType :PositionM
        }
        Offset {
            set msType ms
            set readingType :OffsetM
        }
        Setpoint {
            set msType ""
            set readingType :SetpointM
        }
        Gain {
            set msType ""
            set readingType :GainC
        }
        Error {
            set msType ""
            set readingType :ErrorM
        }
        Unadjusted {
            set msType ""
            set readingType ""
        }
        Adjusted {
            set msType ""
            set readingType :AdjustedM
        }
        default {
            APSSetVarAndUpdate status "No data chosen!"
            return
        }
    }

    APSSetVarAndUpdate status "[clock format [clock seconds] -format %T] -- Collecting data for time 1"
    if [catch {SelectAndAverageData -input $datafile1 -readingType $readingType \
                 -msType $msType -startTime $startTime -window [expr $TimeWindow*60.0]} datafile1] {
        APSSetVarAndUpdate status "$datafile1"
        return
    }
    APSSetVarAndUpdate status "[clock format [clock seconds] -format %T] -- Collecting data for time 2"
    if [catch {SelectAndAverageData -input $datafile2 -readingType $readingType \
                 -msType $msType  -startTime $endTime -window [expr $TimeWindow*60.0]} datafile2] {
        APSSetVarAndUpdate status "$datafile2"
        return
    }

    foreach item [array names processFlag] {
        if !$processFlag($item) continue
        CompareData -readback $readbackChoice -mode $item -datafile1 $datafile1 \
          -datafile2 $datafile2 -msType $msType -readingType $readingType
    }
}

proc CompareData {args} {
    set readback ""
    set readingType ""
    set msType ""
    set mode ""
    set datafile1 ""
    set datafile2 ""
    APSStrictParseArguments {readback readingType msType mode datafile1 datafile2} 

    global dataRootname dataDir
    global StartMonth StartYear StartDay StartHour 
    global EndMonth EndYear EndDay EndHour TimeWindow
    global sectorLowerLimit sectorUpperLimit
    global plotDataLimit plotChangeLimit sectorLowerLimit sectorUpperLimit plotOption extraPlotOptions 

    if $plotDataLimit<=0 {
        set plotDataLimit 10
    }
    if $plotChangeLimit<=0 {
        set plotChangeLimit 10
    }

    if [expr $TimeWindow>2] {
        set extraTitle " averaged over $TimeWindow minutes"
    } else {
        set extraTitle ""
    }
    set plotOptions ""
    if $plotOption(ConnSym) {
        append plotOptions " -grap=sym,conn,sca=1,fil"
    }
    if $plotOption(axes) {
        append plotOptions " -axes=x"
    }
    if $plotOption(names) {
        set xName BPMName
    } else {
        set xName Sector
    }
    if [string length $extraPlotOptions] {
        append plotOptions " $extraPlotOptions"
    }
    switch $mode {
        plotChanges {
            set tmpFile /tmp/[APSTmpString]
            if [catch {exec sddschanges $datafile2 -baseline=$datafile1 $tmpFile \
                         -copy=BPMName,Sector,s -changesIn=*x*,*y*} result] {
                APSSetVarAndUpdate status "$result"
                return
            }
            if [expr $TimeWindow>2] {
                set extraTitle " averaged over $TimeWindow minutes"
            } else {
                set extraTitle ""
            }
            eval exec sddsplot \
              $plotOptions \
              -column=$xName,*x* -column=$xName,*y* \              -separate $tmpFile \
              -filter=col,Sector,$sectorLowerLimit,$sectorUpperLimit \
              -limit=ymin=-$plotChangeLimit,ymax=$plotChangeLimit,autoscal \
              -toptitle \
              \"-title=Change in $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour\" \
              \"-topline=to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle\" \
              &
        }
        plotData {
            eval exec sddsplot \
              $plotOptions \
              -toptitle \
              -limit=ymin=-$plotDataLimit,ymax=$plotDataLimit,autoscal \
              \"-title=Comparison of $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour\" \
              \"-topline=to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle\" \
              -groupby=namestring,filestring \
              -separate=namestring -graphic=line,vary \
              -column=$xName,*x* -column=$xName,*y* $datafile1 \
              -legend=specified=$StartYear/$StartMonth/$StartDay@$StartHour \
              -column=$xName,*x* -column=$xName,*y* $datafile2 \
              -legend=specified=$EndYear/$EndMonth/$EndDay@$EndHour &
        }
        P0Comparison {
            global IDP0File
            if ![file exists $IDP0File] {
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $IDP0File.1 \
                  "-print=column,BPMName,S%02ldB:P0,Sector" \
                  "-print=column,SourceName,ID%ld,Sector" 
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $IDP0File.2 \
                  "-redefine=column,Sector1,Sector 1 +,type=long" \
                  "-print=column,BPMName,S%02ldA:P0,Sector1" \
                  "-print=column,SourceName,ID%ld,Sector" 
                exec sddscombine $IDP0File.1 $IDP0File.2 -merge -pipe=out \
                  | sddsconvert -pipe=in -retain=col,BPMName,SourceName $IDP0File
            }
            if [catch {DisplayBPMChanges -fileList [list $datafile1 $datafile2] \
                         -filterFile $IDP0File \
                         -title "Comparison of $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle"} result] {
                APSSetVarAndUpdate status "$result"
            }
        }
        IDComparison {
            global IDP1File
            if ![file exists $IDP1File] {
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $IDP1File.1 \
                  "-print=column,BPMName,S%02ldB:P1,Sector" \
                  "-print=column,SourceName,ID%ld,Sector" 
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $IDP1File.2 \
                  "-redefine=column,Sector1,Sector 1 +,type=long" \
                  "-print=column,BPMName,S%02ldA:P1,Sector1" \
                  "-print=column,SourceName,ID%ld,Sector" 
                exec sddscombine $IDP1File.1 $IDP1File.2 -merge -pipe=out \
                  | sddsconvert -pipe=in -retain=col,BPMName,SourceName $IDP1File
            }
            if [catch {DisplayBPMChanges -fileList [list $datafile1 $datafile2] \
                         -filterFile $IDP1File \
                         -title "Comparison of $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle"} result] {
                APSSetVarAndUpdate status "$result"
            }
        }
        BMComparison {
            global BMBPMFile
            if ![file exists $BMBPMFile] {
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $BMBPMFile.1 \
                  "-print=column,BPMName,S%02ldB:P3,Sector" \
                  "-print=column,SourceName,BM%ld,Sector" 
                exec sddsprocess /home/helios/oagData/sr/BPLDs/sectors.sdds $BMBPMFile.2 \
                  "-print=column,BPMName,S%02ldB:P4,Sector" \
                  "-print=column,SourceName,BM%ld,Sector" 
                exec sddscombine $BMBPMFile.1 $BMBPMFile.2 -merge -pipe=out \
                  | sddsconvert -pipe=in -retain=col,BPMName,SourceName $BMBPMFile
            }
            if [catch {DisplayBPMChanges -fileList [list $datafile1 $datafile2] \
                         -filterFile $BMBPMFile \
                         -title "Comparison of $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle"} result] {
                APSSetVarAndUpdate status "$result"
            }
        }
        comparison {
            if [catch {DisplayBPMChanges -fileList [list $datafile1 $datafile2] \
                         -title "Comparison of $msType$readingType from $StartYear/$StartMonth/$StartDay@$StartHour to $EndYear/$EndMonth/$EndDay@$EndHour $extraTitle"} result] {
                APSSetVarAndUpdate status "$result"
            }
        }
        default {
            APSSetVarAndUpdate status "$mode not known"
        }
    }

}


proc DisplayBPMChanges {args} {
    set fileList ""
    set filterFile ""
    set title ""
    APSStrictParseArguments {fileList filterFile title}

    set datafile1 [lindex $fileList 0]
    set datafile2 [lindex $fileList 1]
    set tmpFile /tmp/[APSTmpString]
    if ![string length $filterFile] {
        set filterFileCmd cat
        set sourceNameArg ""
    } else {
        set filterFileCmd "sddsxref -pipe $filterFile -match=BPMName -reuse=row,page -take=SourceName -nowarning"
        set sourceNameArg -column=SourceName,label=Source,format=%6s 
    }
    if [catch {exec sddsconvert $datafile2 $datafile2.1 \
                   -nowarning -editnames=column,*x*Mean,ei/2/ \
                   -editnames=column,*y*Mean,ei/2/
        eval exec sddsconvert $datafile1 -pipe=out -nowarning -editnames=column,*x*Mean,ei/1/ \
                   -editnames=column,*y*Mean,ei/1/ \
                   | sddsxref -pipe $datafile2.1 -take=*2 -nowarning \
                   | $filterFileCmd \
                   | sddsprocess -pipe  \
                   \"-define=column,%sChange,%s2 %s1 -,select=*2,edit=ebd,units=mm\" \
                   | sddsprocess -pipe \
                   = 10 um is the tolerance for outlier  = \
                   \"-define=column,%sOut,%sChange abs 10 > ? 1 : 0 \$,select=*Change,edit=%/Change//\" \
                   | sddsrowstats -pipe -sum=NumberOut,*Out \
                   | tee $tmpFile.sdds \
                   | sddsprintout -pipe=in $tmpFile.print \
                   \"-title=$title\" $sourceNameArg \
                   -column=BPMName,label=BPM,format=%8s \
                   -format=double=%10.3f \
                   -column=*x*1,label=x1 -column=*x*2,label=x2 -column=*x*Change,label=xDelta \
                   -column=*y*1,label=y1 -column=*y*2,label=y2 -column=*y*Change,label=yDelta \
                   \"-column=NumberOut,format=%8.0f,label=#>10um\" } result] {
        return -code error "$result"
    }

    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpFile.print \
      -sddsExportableFile $tmpFile.sdds -width 100 -printCommand "enscript -r" \
      -deleteOnClose 1
}

proc SelectAndAverageData {args} {
    set input ""
    set readingType ""
    set msType ""
    set startTime ""
    set window ""
    APSStrictParseArguments {input readingType msType startTime window}
    global dataDir xrefDir

    set output /tmp/[APSTmpString]
    if [expr $window<=2] {
        set filterArg [list -filter=column,Time,$startTime,1e10 -clip=1,0,invert]
    } else {
        set filterArg -filter=column,Time,$startTime,[expr $startTime+$window]
    }
    set retain Time*,S-DCCT:CurrentM
    if [string length $readingType] {
        set retain $retain,*${msType}*${readingType}*
        set delete *ID*,*BM*
        set tmpFile /tmp/[APSTmpString]
        if [catch {eval exec sddscombine $input -pipe=out \
                     -retain=column,$retain \
                     | sddsconvert -pipe=in $tmpFile -delete=column,$delete} result] {
            return -code error "SelectAndAverageData1: $result"
        }
        if [catch {KeepXYPairs -filename $tmpFile -readingType $readingType} results] {
            return -code error "SelectAndAverageData2: $results"
        }
        if [catch {eval exec  sddsprocess $tmpFile -pipe=out $filterArg \
                     -nowarning \
                     -filter=column,S-DCCT:CurrentM,2,300 \
                     \"-test=parameter,n_rows 1 > \" \
                     -process=Time,first,Time0 -process=*${msType}*,ave,%sMean \
                     | sddscollapse -pipe \
                     | sddscollect -pipe \
                     -collect=suffix=${msType}:x${readingType}Mean \
                     -collect=suffix=${msType}:y${readingType}Mean \
                     | sddsxref -pipe $xrefDir/SRBPMPosition.xref -take=* -nowarning \
                     -reuse=page -match=Rootname=BPMName \
                     | sddssort -pipe=in -column=s $output} result] {
            file delete $tmpFile
            return -code error "SelectAndAverageData3: $result"
        } else {
            file delete $tmpFile
        }
    } else {
        set retain $retain,*${msType}*x,*${msType}*y
        set delete *ID*,*BM*
        set tmpFile /tmp/[APSTmpString]
        if [catch {eval exec sddscombine $input -pipe=out \
                     -retain=column,$retain \
                     | sddsconvert -pipe=in $tmpFile -delete=column,$delete} result] {
            return -code error "SelectAndAverageData4: $result"
        }
        if [catch {KeepXYPairs -filename $tmpFile} results] {
            return -code error "SelectAndAverageData5: $results"
        }
        if [catch {eval exec sddscombine $tmpFile -pipe=out \
                     -retain=column,$retain \
                     | sddsconvert -pipe -delete=column,$delete \
                     | sddsprocess -pipe $filterArg \
                     -nowarning \
                     -filter=column,S-DCCT:CurrentM,2,300 \
                     \"-test=parameter,n_rows 1 > \" \
                     -process=Time,first,Time0 -process=*${msType}*,ave,%sMean \
                     | sddscollapse -pipe \
                     | sddscollect -pipe \
                     -collect=suffix=${msType}:xMean \
                     -collect=suffix=${msType}:yMean \
                     | sddsxref -pipe $xrefDir/SRBPMPosition.xref -take=* -nowarning \
                     -reuse=page -match=Rootname=BPMName \
                     | sddssort -pipe=in -column=s $output} result] {
            return -code error "SelectAndAverageData: $result"
        }
    }
    return -code ok $output
}

proc KeepXYPairs {args} {
    set filename ""
    set readingType ""
    APSStrictParseArguments {filename readingType}
    if {[catch {exec sddsquery $filename -col} cols]} {
        return -code error $cols
    }
    set cols [lsort $cols]
    if [string length $readingType] {
        foreach "c" $cols {
            set len [expr [string length ${readingType}] + 1]
            if {[string compare :x$readingType [string range $c end-${len} end]] == 0} {
                lappend xCols $c
            } elseif {[string compare :y$readingType [string range $c end-${len} end]] == 0} {
                lappend yCols $c
            }
        }
    } else {
        foreach "c" $cols {
            set len 1
            if {[string compare :x [string range $c end-${len} end]] == 0} {
                lappend xCols $c
            } elseif {[string compare :y [string range $c end-${len} end]] == 0} {
                lappend yCols $c
            }
            
        }
    }
    set filterCols ""
    foreach x $xCols {
        set len [expr 2 + [string length ${readingType}]]
        set i [string first [string range $x 0 end-$len] $yCols]
        if {$i == -1} {
            lappend filterCols $x
        }
    }
    foreach y $yCols {
        set len [expr 2 + [string length ${readingType}]]
        set i [string first [string range $y 0 end-$len] $xCols]
        if {$i == -1} {
            lappend filterCols $y
        }
    }
    if {[llength $filterCols]} {
        if {[catch {exec sddsconvert $filename -delete=column,[join $filterCols ,] -nowarn} results]} {
            return -code error $results
        }
        file delete ${filename}~
    }
}

set plotOptions ""
MakeDateTimeFrame .date -parent .userFrame
update
MakePlotControls .plcontrol -parent .userFrame -label "Plot Controls"
MakeButtonRow .buttons -parent .userFrame -packOption "-side bottom"
update

# **************************** Emacs Editing Sequences *****************
# Local Variables:
# mode: tcl
# End:
