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


set SRDirectory /home/helios/oagData/sr/bpmSelfTest
set BoosterDirectory /home/helios/oagData/booster/bpmSelfTest

# Use the /tmp directory for upgrade/debugging purposes.
# set directory /tmp

# Only use for upgrade/debugging purposes.
# source ../../mplib/sr/SRBPMSelfTestWidgets.tcl

# This procedure sets the status variable used by the status widget.

proc SetStatus {text} {
    global ControlStatus
    set ControlStatus $text
    update
}

#Disable buttons once one is pressed.

proc DisableSelfTestButton {} {
    APSDisableButton .userFrame.selfTestWidgets.frame.selfTestButton.button
  #  APSDisableButton .userFrame.selfTestWidgets.frame.fileSelectionFrame.button
  #  APSDisableButton .userFrame.selfTestWidgets.frame.processSelectionFrame.button
    APSDisableButton .userFrame.plotFrame.frame.plotSelectionFrame.button
    APSDisableButton .userFrame.selfTestWidgets.frame.cleanupSelectionFrame.button
    APSDisableButton .userFrame.selfTestWidgets.frame.updateContentsFrame.button
}

#Enable buttons once one is pressed and its associated procedure finishes.

proc EnableSelfTestButton {} {
    APSEnableButton .userFrame.selfTestWidgets.frame.selfTestButton.button
  #  APSEnableButton .userFrame.selfTestWidgets.frame.fileSelectionFrame.button
  #  APSEnableButton .userFrame.selfTestWidgets.frame.processSelectionFrame.button
    APSEnableButton .userFrame.plotFrame.frame.plotSelectionFrame.button
    APSEnableButton .userFrame.selfTestWidgets.frame.cleanupSelectionFrame.button
    APSEnableButton .userFrame.selfTestWidgets.frame.updateContentsFrame.button
}

# Checks the SR BPM local bus addresses for errors.  If errors are
# detected, an sddsfile is made in $directory and sddsprintout is used
# to display the specific BPMs with errors, sector number, and IOC
# number.  Returns 0 if there are errors; 1 if there are no errors.

#Perform the BPM self-test.  Returns a 1 if the test was successful; 
#returns a 0 if not.

proc PerformBPMSelfTest {args} {

    global ControlStatus selectedBPMList SelfTestDataFileName SelfTestDataFileRootName
    global MostRecentFileName directory contentsString system

    DisableSelfTestButton
    APSParseArguments {statusCallback}
    
    if {$system=="SR"} {
        set AccessMode [exec cavget -list=S:bpm:accessControlMBBO.VAL -pendIoTime=10]
        if {[lsearch -exact [list Unlimited Maintenance] $AccessMode]==-1} {
            if {$statusCallback!=""} {
                $statusCallback "Error:  The SR BPM access mode must be set to \"Maintenance\" or \"Unlimited\" to perform the self-test."
            }       
            APSAlertBox .alert -errorMessage "Error:  The SR BPM access mode must be set to \"Maintenance\" or \"Unlimited\" to perform the self-test."
            EnableSelfTestButton
            bell
            return 0
        }
    }
    set selectedBPMList ""
    set selectedBPMList [MakeSelectedBPMList]
    if {$selectedBPMList==""} {
        $statusCallback "No BPMs Selected."
        EnableSelfTestButton
        bell
        return 0
    }
    scan [DetermineMostRecentFileIndex $SelfTestDataFileRootName] %ld fileIndex
    incr fileIndex
    set fileIndex [format %03ld $fileIndex]
    if {$MostRecentFileName==""} {
        set fileIndex [DetermineMostRecentFileIndex $SelfTestDataFileRootName]
    }
    set SelfTestDataFileName ${SelfTestDataFileRootName}.${fileIndex}.sdds
    PerformBPMSelfTestSetup -statusCallback SetStatus
    AcquireBPMSelfTestData -statusCallback SetStatus
    RestoreBPMSetup -statusCallback SetStatus
    bell
    EnableSelfTestButton
    #process
    RegroupAndHistogramSelfTestData
    return 1
}

# Make a list of BPMs selected using the checkbuttons.  Procedure returns the list.

proc MakeSelectedBPMList {} {

    global bpmList system
    
    switch $system {
        SR {
            set start S
	    set sectorCount 40
        }
        Booster {
            set start B
	    set sectorCount 4
        }
    }
    set selectedList ""
    for {set sector 1} {$sector<=$sectorCount} {incr sector} {
        foreach bpm $bpmList {
            set flagName bpmS${sector}$bpm
            global $flagName
            if {[set $flagName]} {
                lappend selectedList ${start}${sector}${bpm}
            }
        }
    }
    return $selectedList
}

# Execute commands to configure each BPM for the self-test.  Returns 1 after executing the BPM configuration commands.

proc PerformBPMSelfTestSetup {args} {

    global ControlStatus gain MSavg oldMSavg system
    global averagingState

    APSParseArguments {statusCallback}
    if {$statusCallback!=""} {
        $statusCallback "Configuring Selected BPMs for the self-test..."
    }       

    set unLockBPMCommand [ComposeCavputCavgetCommand cavput lock_bo.VAL Unlocked 1]
    set backupTriggerOnCommand [ComposeCavputCavgetCommand cavput backuptrig_bo.VAL On 1]
    set FFRunOnCommand [ComposeCavputCavgetCommand cavput ffreerun_bo.VAL On 1]
    set GainSetCommand [ComposeCavputCavgetCommand cavput normal_bo.VAL $gain 1]
    switch $system {
	SR {
	    set ring SR
	}
	Booster {
	    set ring Sync
	}
    }
    set RingToSRCommand [ComposeCavputCavgetCommand cavput  ring_bo.VAL $ring 1]
    set ResyncToInhibitCommand [ComposeCavputCavgetCommand cavput resync_bo.VAL Inhibit 1]
    set MemoryScannerBoxAvgWt [ComposeCavputCavgetCommand cavput ms.BXWT $MSavg 1]
    eval exec $unLockBPMCommand
    eval exec $backupTriggerOnCommand
    eval exec $FFRunOnCommand
    eval exec $GainSetCommand
    eval exec $RingToSRCommand
    eval exec $ResyncToInhibitCommand 
    set oldMSavg [exec cavget -list=S:bpm:memscan_wt_ao.VAL]
    eval exec $MemoryScannerBoxAvgWt
    if {$system=="SR"}  {
        if {[catch {exec cavget -pend=15 -list=S  \
                        -range=beg=1,end=37 -list=A:P1,A:P2,A:P3,A:P4,B:P5,B:P4,B:P3,B:P2,B:P1 \
                        -list=:msAve:AveEnbBO -cavputForm} averagingState]} {
            if {$statusCallback!=""} {
                $statusCallback "Error getting bpm averaging state: ${averagingState}."
            }
            return -code error "Error getting bpm averaging state: ${averagingState}."
        }
    # some sector BPMs are FPGA and no longer have :msAve:AveEnbB PVs.
	if {[catch {exec cavget -pend=15 -list=S  \
                        -range=beg=39,end=40 -list=A:P1,A:P2,A:P3,A:P4,B:P5,B:P4,B:P3,B:P2,B:P1 \
                        -list=:msAve:AveEnbBO -cavputForm} averagingState]} {
            if {$statusCallback!=""} {
                $statusCallback "Error getting bpm averaging state: ${averagingState}."
            }
            return -code error "Error getting bpm averaging state: ${averagingState}."
        }
        if {[catch {exec cavput -pend=15 -list=S  \
                        -range=beg=1,end=34 \
			-list=A:P1,A:P2,A:P3,A:P4,B:P5,B:P4,B:P3,B:P2,B:P1 \
                        -list=:msAve:AveEnbBO=Disable} result]} {
            if {$statusCallback!=""} {
                $statusCallback "Error setting bpm averaging state: ${result}."
            }
            return -code error "Error setting bpm averaging state: ${result}."
        }
	if {[catch {exec cavput -pend=15 -list=S  \
                        -list=37,39,40 \
			-list=A:P1,A:P2,A:P3,A:P4,B:P5,B:P4,B:P3,B:P2,B:P1 \
                        -list=:msAve:AveEnbBO=Disable} result]} {
            if {$statusCallback!=""} {
                $statusCallback "Error setting bpm averaging state: ${result}."
            }
            return -code error "Error setting bpm averaging state: ${result}."
        }
    }
    if {$statusCallback!=""} {
        $statusCallback "Selected BPMs configured for the self-test."
    }       
    return 1
}

proc RestoreBPMSetup {args} {

    global ControlStatus gain MSavg oldMSavg system
    global averagingState
    set gain 0
    
    APSParseArguments {statusCallback}
    if {$statusCallback!=""} {
        $statusCallback "Restoring standard BPM configuration..."
    }       
    #        set lockBPMCommand [ComposeCavputCavgetCommand cavput lock_bo.VAL Locked]
    if {$system=="SR"} {
        if [catch {exec cavput -pend=15 -list=$averagingState} result] {
            if {$statusCallback!=""} {
                $statusCallback "Error restoring BPM averaging state: $result"
            }
            return -code error "$result"
        }
    }
        
    set backupTriggerOffCommand [ComposeCavputCavgetCommand cavput backuptrig_bo.VAL Off 1]
    set FFRunOffCommand [ComposeCavputCavgetCommand cavput ffreerun_bo.VAL Off 1]
    set GainSetCommand [ComposeCavputCavgetCommand cavput normal_bo.VAL $gain 1]
    switch $system {
	SR {
	    set ring SR
	}
	Booster {
	    set ring Sync
	}
    }
    set RingToSRCommand [ComposeCavputCavgetCommand cavput  ring_bo.VAL $ring 1]
    set ResyncToInhibitCommand [ComposeCavputCavgetCommand cavput resync_bo.VAL Inhibit 1]
    set MemoryScannerBoxAvgWt [ComposeCavputCavgetCommand cavput ms.BXWT $oldMSavg 1]
    eval exec $FFRunOffCommand
    eval exec $backupTriggerOffCommand
    #        eval exec $lockBPMCommand
    eval exec $GainSetCommand
    eval exec $RingToSRCommand
    eval exec $ResyncToInhibitCommand 
    eval exec $MemoryScannerBoxAvgWt
    
    if {$statusCallback!=""} {
        $statusCallback "BPM standard configuration restored."
    }       
    return 1
}

# Compose cavput and cavget commands relevant for the self-test for
# the selected BPMs.  Procedure returns the command.  Procedure takes
# as input the channel access action (cavput or cavget) along with a
# pvNameString and a pvCommand (ie. On or Off) for the case of cavput.
# For cavget, pvCommand is considered a dummy variable.

proc ComposeCavputCavgetCommand {action pvNameString pvCommand exclude38} {

    global selectedBPMList
    set bpmList ""
    if $exclude38 {
	foreach bpm $selectedBPMList {
	    if ![regexp {S38} $bpm] {
		lappend bpmList $bpm
	    }
	}
    } else {
	set bpmList $selectedBPMList
    }

    switch $action {
        cavput {
            set Command "cavput -list=[join $bpmList ,] -list=:$pvNameString=$pvCommand -pendIOTime=10"
        }
        cavget {
            set Command "cavget -list=[join $bpmList ,] -list=:$pvNameString -pendIOTime=10 -errorValue=-999"
        }
    }
    return $Command
}


# Compose the SDDS self-test data file header.  Returns 1 when finished.

proc ComposeSddsmonitorInputDataFile {sddsFileID} {

    global selectedBPMList system
    
    puts $sddsFileID "SDDS1\n&description text = \"SR BPM self-test sddsmonitor PV list file\", &end"
    puts $sddsFileID "&column name = ControlName,  description = \"BPM quantity PV name\", type = string, &end"
    puts $sddsFileID "&column name = ReadbackName,  description = \"BPM quantity name\", type = string, &end"
    puts $sddsFileID "&column name = ReadunitsName,  description = \"BPM quantity units name\", type = string, &end"
    puts $sddsFileID "&data mode = ascii, no_row_counts=1 &end"

    foreach bpm $selectedBPMList {
        puts $sddsFileID "${bpm}:scduRaw:x.RVAL ${bpm}:RawSCDUX   Counts"
        puts $sddsFileID "${bpm}:scduRaw:y.RVAL ${bpm}:RawSCDUY   Counts"
        puts $sddsFileID "${bpm}:sum.RVAL       ${bpm}:RawSCDUSum Counts"
        switch $system {
            SR {
                puts $sddsFileID "${bpm}:ms.XMON ${bpm}:RawMSX    Counts"
                puts $sddsFileID "${bpm}:ms.YMON ${bpm}:RawMSY    Counts"
                puts $sddsFileID "${bpm}:ms.IMON ${bpm}:RawMSSum  Counts"
                puts $sddsFileID "${bpm}:ms.XAVE ${bpm}:RawMSAvgX Counts"
                puts $sddsFileID "${bpm}:ms.YAVE ${bpm}:RawMSAvgY Counts"
                set AP2BPMFlag [string first A:P2 $bpm]
                if {${AP2BPMFlag}==-1} {
                    puts $sddsFileID "SRFB:${bpm}:ms:x ${bpm}:RawFBMSx Counts"
                    puts $sddsFileID "SRFB:${bpm}:ms:y ${bpm}:RawFBMSy Counts"
                }
            }
            Booster {
                puts $sddsFileID "${bpm}:ms:x.VAL ${bpm}:PositionX mm"
                puts $sddsFileID "${bpm}:ms:y.VAL ${bpm}:PositionY mm"
                puts $sddsFileID "${bpm}:scdu:x.VAL ${bpm}:SCDUX   mm"
                puts $sddsFileID "${bpm}:scdu:y.VAL ${bpm}:SCDUY   mm"
            }
        }
    }
    return 1
}

# Acquire the self-test data: compose required cavput and cavget commands and run the self-test.  Returns 1 when finished.

proc AcquireBPMSelfTestData {args} {

    global ControlStatus selectedBPMList SelfTestDataFileRootName SelfTestDataFileName 
    global number multiplier MSavg gain abortFlag directory processFlag contentsString system

    set number [expr int(pow(2,$MSavg) * $multiplier)]

    APSParseArguments {statusCallback}
    
    set SelfTestSddsmonitorFileName $SelfTestDataFileRootName.[lindex [split $SelfTestDataFileName {.}] 1].mon

    set SelfTestCavputOnCommand [ComposeCavputCavgetCommand cavput test_bo.VAL On 1]
    set SelfTestCavputOffCommand [ComposeCavputCavgetCommand cavput test_bo.VAL Off 1]

    set AcquireDataCommandList ""
    set AcquireDataCommand ""

    if {$statusCallback!=""} {
        $statusCallback "Performing the BPM self-test and acquiring data for selected BPMs..."
    }       

    # Open the SDDS data file and compose the SDDS header

    set sddsFileID [open $SelfTestSddsmonitorFileName w+]
    ComposeSddsmonitorInputDataFile $sddsFileID 
    close $sddsFileID

    # for loop to execute $number of self-tests.

    set sddsMonitorErrorLog /tmp/[APSTmpString]
    set sddsMonitorFileID [open "|sddsmonitor $SelfTestSddsmonitorFileName \
           $SelfTestDataFileName \
           -erase -single=stdout -steps=$number -update=1 2> $sddsMonitorErrorLog" r+]
    set processFlag 1
    set abortFlag 0
    fileevent $sddsMonitorFileID readable \
      "sddsmonitorCallback $sddsMonitorFileID processFlag -statusCallback SetStatus"
    for {set i 0} {$i < $number} {incr i 1} {
        if {$processFlag==1 && $abortFlag==0} {
            tkwait variable processFlag
        }
        set processFlag 1
        update
        if {$abortFlag==0} {eval exec $SelfTestCavputOnCommand}
        update
        after 1000
        if {$abortFlag==0} {eval exec $SelfTestCavputOffCommand}
        update
        after 1000
        update
        if {$abortFlag==1 || $processFlag==-1} {
            set abortNumber [expr $i + 1]
            bell
            break
        } elseif {[expr fmod($i + 1,10)]==0} { 
            if {$statusCallback!=""} {
                $statusCallback "[expr $i + 1] self-tests completed."
            }
            bell
        }
        if {$abortFlag==0} {
            puts $sddsMonitorFileID "y"
            flush $sddsMonitorFileID
        }
        update
    }
    close $sddsMonitorFileID
    if [file size $sddsMonitorErrorLog]!=0 {
        APSFileDisplayWindow [APSUniqueName .] \
          -fileName $sddsMonitorErrorLog -comment "Errors from sddsmonitor process" \
          -deleteOnClose 1 -width 132 -height 30 -printCommand "enscript -r" 
    } else {
        catch {file delete $sddsMonitorErrorLog}
    }
    set PWD [exec pwd]
    cd $directory

    # Record memory scanner average factor and gain mode here.
    # Also, convert to binary to "fix" bug in processing segment of the script.

    if {!$gain} {
        set gainMode "Low"
    } else {set gainMode "High"}
    exec sddsconvert $SelfTestDataFileName -binary -nowarning 
    if [catch  {exec sddsprocess $SelfTestDataFileName -nowarning \
                  -define=param,MSBoxAvgWt,$MSavg,type=long \
                  -define=param,Factor,$multiplier,type=long \
                  -print=param,GainMode,$gainMode \
                  -print=param,Contents,[APSMakeSafeQualifierString $contentsString]} result] {
        return -code error "$result"
    }
    catch {file delete ${SelfTestDataFileName}~ $SelfTestSddsmonitorFileName}
    exec gzip $SelfTestDataFileName
    set SelfTestDataFileName ${SelfTestDataFileName}.gz
    cd $PWD
    if {$statusCallback!="" && $abortFlag==0} {
        $statusCallback "BPM self-test data acquisition completed.  $number self-tests completed."
    } elseif {$statusCallback!="" && $abortFlag==1} {
        $statusCallback "BPM self-test data acquisition aborted.  $abortNumber self-tests completed."
    }
    return 1
}

# Callback routine for sddsmonitor subprocess in single-shot mode written by M. Borland.

proc sddsmonitorCallback {fid flagVariable args} {
    
    global ControlStatus
    APSParseArguments {statusCallback}
    gets $fid input
    global $flagVariable
    #        puts stderr "[subst \$$flagVariable]  $input"
    if [string compare $input "Type <cr> to read, q to quit:"]==0 {
        set $flagVariable 0
        #                puts stderr "[subst \$$flagVariable]  $input"
        return
    }
    if [string compare $input "Done."]==0 {
        set $flagVariable 2
        #                puts stderr "[subst \$$flagVariable]  $input"
        return
    }
    if [string length $input] {
        # unknown string returned
        set $flagVariable -1
        if {$statusCallback!=""} {
            $statusCallback "Unknown response from sddsmonitor while acquiring data..."
            $statusCallback "$input"
        }
    }
}

# Determines the proper file index for the self test data file based on the most recent version of the file.

proc DetermineMostRecentFileIndex {fileRootName} {

    global MostRecentFileName
    set MostRecentFileName [lindex [lsort -decreasing [glob -nocomplain ${fileRootName}.*]] 0]

    if {$MostRecentFileName!=""} {
        set index [lindex [split $MostRecentFileName .] 1]
    } else {set index [format %03ld 0]}
    return $index
}

# Gets the selected data file using APSFileSelectDialog.  If no file is selected (Cancel is pressed) the procedure
# gets the most recent existing data file.
set CompareDataFileName ""
proc GetSelectedDataFile {args} {
    set compareData 0
    set statusCallback ""

    global SelfTestDataFileName contentsString directory ControlStatus bpmList CompareDataFileName contentsString1 system
    APSParseArguments {statusCallback compareData}
    
    if {$compareData} {
        set fileVar CompareDataFileName
        set contentVar contentsString1
    } else {
        set fileVar  SelfTestDataFileName
        set contentVar contentsString
    }
    set files [lsort -decreasing [glob -nocomplain $directory/SelfTestData-*.sdds.gz]]
  
    regsub -all $directory/ $files "" files0
    regsub -all {.gz} $files0 "" files
    global fileSelection
    set fileSelection ""
    APSScrolledListWindow .display$system -name "$system file selection" \
        -label "Select a flile"  -acceptButton 0 \
        -itemList $files -selectionVar fileSelection \
        -directory $directory -appendDescription 1 \
        -rootnameOnly 1 -descriptionName Contents 
    tkwait variable fileSelection
    if ![string length $fileSelection] {
        SetStatus "No file is chosen."
        return
    }
    set fileSelection [lindex [lindex $fileSelection 0] 0]
    set $fileVar $directory/${fileSelection}.gz
   
    set file [set $fileVar]
    set ProcessedDataFileFlag [lindex [split $file {.}] 2]
    if {$file!=""} {
        if {$ProcessedDataFileFlag=="Reg" || $ProcessedDataFileFlag=="Hist" || \
                $ProcessedDataFileFlag=="MeanRaw" || $ProcessedDataFileFlag=="FBHist" || \
                $ProcessedDataFileFlag=="FBMeanRaw" || $ProcessedDataFileFlag=="FBReg" || \
                $ProcessedDataFileFlag=="mon"} {
            set $fileVar [join "[lindex [split $file {.}] 0] \
                                                        [lindex [split $file {.}] 1] sdds gz" {.}]
        } else {set $fileVar $file}
    }
   
    if {!$compareData} {
        GetBPMNamesFromSelectedFile -file $file
    }
    if [catch {exec sddsprintout $file -param=Contents} result] {
        if {$statusCallback!=""} {
            $statusCallback "No contents string defined in $file."
        }
        return 0
    } else {
        set $contentVar [exec sdds2stream $file -noquotes -parameter=Contents]
        return 1
    }
}

# This procedure gets bpm names from a selected file
# and selects the bpms on the bpm select widget.
# Returns 1 when completed.

proc GetBPMNamesFromSelectedFile {args} {
    set file ""
    APSParseArguments {file}
    global SelfTestDataFileName directory bpmList system
    set tmpFile /tmp/[APSTmpString]
    APSAddToTempFileList $tmpFile
    
    if [catch {exec sddsconvert $file -pipe=out -toPage=1 \
                   | sddscollect -pipe=in $tmpFile -collect=suffix=:RawSCDUX } result] {
        return -code error "GetBPMNamesFromSelectedFile: $result while processing $file"
    }
    
    if [catch {APSGetSDDSColumn -fileName $tmpFile -column Rootname} fileBPMList] {
        return -code error "GetBPMNamesFromSelectedFile: $fileBPMList while getting column names"
    }
    catch {file delete $tmpFile}

    switch $system {
        SR {
            set sectorCount 40
            set start S
        }
        Booster {
            set sectorCount 4
            set start B
        }
    }
  
    foreach bpm $bpmList {
        set bpmFamilyCount 0
        for {set sector 1} {$sector<=$sectorCount} {incr sector} {
            set BPMName1 ${start}${sector}${bpm}
            set BPMName S${sector}${bpm}
            if {[lsearch -exact $fileBPMList $BPMName1]==-1} {
                set nameFlag bpm${BPMName}
                if {![info exists $nameFlag]} {
                    global $nameFlag
                    set $nameFlag 0
                }
            } else {
                set nameFlag bpm${BPMName}
                if {![info exists $nameFlag]} {
                    global $nameFlag
                    set $nameFlag 1
                }
                incr bpmFamilyCount
            }
        }
        set togVar bpmS${bpm}
        global $togVar
        if {${bpmFamilyCount}==$sectorCount} {
            if {[info exists $togVar]} {
                set $togVar 1
            }
        } else {
            if {[info exists $togVar]} {
                set $togVar 0
            }
        }
    }
    return 1
}

# This procedure regroups, histograms and collapses the self-test data.  Returns a 1 when finished.  Returns 0 if the
# self-test data file does not exist.

proc RegroupAndHistogramSelfTestData {args} {
    set compareData 0 
    set statusCallback SetStatus
    APSParseArguments {compareData statusCallback}
    
    global SelfTestDataFileName directory system suffixList CompareDataFileName
    
    if $compareData {
        set file $CompareDataFileName
    } else {
        set file $SelfTestDataFileName 
    }
    if {![file exists $file]} {
        SetStatus "Pease select an existing self-test data file." 
        return 0
    }    
    
    set RegroupedDataFileName  \
        [join "[lindex [split $file {.}] 0] . \
             [lindex [split $file {.}] 1] .Reg.sdds" {}]
    set HistogramDataFileName  \
        [join "[lindex [split $file {.}] 0] . \
             [lindex [split $file {.}] 1] .Hist.sdds" {}]
    set MeanRawDataFileName \
        [join "[lindex [split $file {.}] 0] . \
      [lindex [split $file {.}] 1] .MeanRaw.sdds" {}]
    
    if {$system=="SR"} {
        set RegroupedFBDataFileName  \
            [join "[lindex [split $file {.}] 0] . \
      [lindex [split $file {.}] 1] .FBReg.sdds" {}]
        set HistogramFBDataFileName  \
            [join "[lindex [split $file {.}] 0] . \
      [lindex [split $file {.}] 1] .FBHist.sdds" {}]
        set MeanRawFBDataFileName \
            [join "[lindex [split $file {.}] 0] . \
      [lindex [split $file {.}] 1] .FBMeanRaw.sdds" {}]
    }
    if {$statusCallback!=""} {
        $statusCallback "Processing $file self-test data file..."
    }       
    
    set MSBoxCarAverage [exec sdds2stream $file -param=MSBoxAvgWt]
    set MultFactor [exec sdds2stream $file -param=Factor]
    set GainMode [exec sdds2stream $file -param=GainMode]
    set SelfTestNumber [lindex [exec sdds2stream $file -rows] 0]
    
    foreach suffix $suffixList {
        lappend collectOpt -collect=suffix=$suffix
        lappend procOpt -process=$suffix,average,Mean[string range $suffix 1 end]
    }
   
    eval exec sddscollect -pipe=out $file  $collectOpt \
        | sddsxref -pipe $directory/Orbit.req -match=Rootname=BPMName \
        -take=Index \
        -reuse=page \
        | sddsconvert -pipe -rename=col,Index=BPMIndex \
        | sddssort -pipe -col=BPMIndex,increasing \
        | sddsregroup -pipe -newParameter=BPMIndex,Rootname \
        -newColumn=Step \
        | sddsconvert -pipe=in,out -rename=col,Step=SelfTestNumberIndex \
        | sddsprocess -pipe=in $RegroupedDataFileName \
        $procOpt \
        -define=param,SelfTestNumber,$SelfTestNumber,type=long \
        -define=param,MSBoxAvgWt,$MSBoxCarAverage,type=long \
        -define=param,Multiplier,$MultFactor,type=long \
        -print=param,GainMode,$GainMode,type=string \
        \"-print=param,SelfTestNumberString,Self-Test Number = $SelfTestNumber,type=string\" \
        \"-print=param,MSBoxAvgWtString,Memory Scanner Avg = $MSBoxCarAverage,type=string\" \
        \"-print=param,MultiplierString,Self-Test Multiplier = $MultFactor,type=string\" \
        \"-print=param,GainModeString,Gain Mode = $GainMode,type=string\"
    
    exec sddsmultihist $RegroupedDataFileName -pipe=out \
        -column=:Raw*       \
        -sizeOfBins=1       \
        -abscissa=RawCounts \
        | sddsxref -pipe=in $RegroupedDataFileName \
        $HistogramDataFileName \
        -transfer=param,BPMIndex,Rootname,Mean*,SelfTestNumber,MSBoxAvgWt,GainMode \
        -leave=*

    exec sddscollapse $HistogramDataFileName  -pipe=out -nowarnings \
      | sddsprocess -pipe=in $MeanRawDataFileName \
      "-print=param,SelfTestNumberString,Self-Test Number = $SelfTestNumber,type=string" \
      "-print=param,MSBoxAvgWtString,Memory Scanner Avg = $MSBoxCarAverage,type=string" \
      "-print=param,MultiplierString,Self-Test Multiplier = $MultFactor,type=string" \
      "-print=param,GainModeString,Gain Mode = $GainMode,type=string"

    # Check to see that the file contains more bpm pvs than the A:P2s.  The A:P2s do not have feedback PVs
    # defined so the following processing would generate an error.
    if {$system=="SR"} {
        set colList [APSGetSDDSNames -fileName $file -class column]
        set onlyAP2Flag [lsearch -glob $colList *FBMS*]
        if {${onlyAP2Flag}!=-1} {
            exec sddscollect -pipe=out $file \
                -collect=suffix=:RawFBMSx \
                -collect=suffix=:RawFBMSy \
                | sddsxref -pipe=in,out $directory/Orbit.req -match=Rootname=BPMName \
                -take=Index \
                -reuse=page \
                | sddsconvert -pipe=in,out -rename=col,Index=BPMIndex \
                | sddssort -pipe=in,out -col=BPMIndex,increasing \
                | sddsregroup -pipe=in,out -newParameter=BPMIndex,Rootname \
                -newColumn=Step \
                | sddsconvert -pipe=in,out -rename=col,Step=SelfTestNumberIndex \
                | sddsprocess -pipe=in $RegroupedFBDataFileName \
                -process=:RawFBMSx,average,MeanRawFBMSx \
                -process=:RawFBMSy,average,MeanRawFBMSy \
                -define=param,SelfTestNumber,$SelfTestNumber,type=long \
                -define=param,MSBoxAvgWt,$MSBoxCarAverage,type=long \
                -define=param,Multiplier,$MultFactor,type=long \
                -print=param,GainMode,$GainMode,type=string \
                "-print=param,SelfTestNumberString,Self-Test Number = $SelfTestNumber,type=string" \
                "-print=param,MSBoxAvgWtString,Memory Scanner Avg = $MSBoxCarAverage,type=string" \
                "-print=param,MultiplierString,Self-Test Multiplier = $MultFactor,type=string" \
                "-print=param,GainModeString,Gain Mode = $GainMode,type=string"
        
            exec sddsmultihist -pipe=out $RegroupedFBDataFileName \
                -column=:Raw*       \
                -sizeOfBins=1       \
                -abscissa=RawCounts \
                | sddsxref -pipe=in $RegroupedFBDataFileName \
                $HistogramFBDataFileName \
                -transfer=param,BPMIndex,Rootname,MeanRawFBMSx,MeanRawFBMSy,SelfTestNumber,MSBoxAvgWt,GainMode \
                -leave=*

            exec sddscollapse -pipe=out $HistogramFBDataFileName -nowarnings \
                | sddsprocess -pipe=in $MeanRawFBDataFileName \
                "-print=param,SelfTestNumberString,Self-Test Number = $SelfTestNumber,type=string" \
                "-print=param,MSBoxAvgWtString,Memory Scanner Avg = $MSBoxCarAverage,type=string" \
                "-print=param,MultiplierString,Self-Test Multiplier = $MultFactor,type=string" \
                "-print=param,GainModeString,Gain Mode = $GainMode,type=string" 
        }
    }
    if {$statusCallback!=""} {
        $statusCallback "Self-test data file $file processed."
    }       
    bell
    return 1
}       

proc CompareBPMSelfTestData {args} {
    
    global SelfTestDataFileRootName SelfTestDataFileName system CompareDataFileName
    global dataFlag histFlag averageFlag

    if ![string length $CompareDataFileName] {
        return -code error "Compare data file is not provided."
    }
    
    foreach file [list $CompareDataFileName $SelfTestDataFileName] flag {1 2} {
        set fileIndex$flag [lindex [split $file {.}] 1]
        set rootname$flag [lindex [split $file {.}] 0]
        
        set RegroupedFileName$flag \
            [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .Reg.sdds" {}]
        set HistogramFileName$flag \
            [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .Hist.sdds" {}]
        set MeanRawFileName$flag \
            [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .MeanRaw.sdds" {}]
       
        if {![file exists [set RegroupedFileName$flag]] ||
            ![file exists [set HistogramFileName$flag]] ||
            ![file exists [set MeanRawFileName$flag]]} {
            SetStatus "Self-test data file $file must be processed\n(or collected) \
                                         before plotting."
            return
        }
        if {$system=="SR"} {
            set colList [APSGetSDDSNames -fileName $file -class column]
            set onlyAP2Flag$flag [lsearch -glob $colList *FBMS*]
            set onlyAP2Flag [set onlyAP2Flag$flag]
            if {${onlyAP2Flag}!=-1} {
                set RegroupedFBFileName$flag \
                    [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .FBReg.sdds" {}]
                set HistogramFBFileName$flag \
                    [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .FBHist.sdds" {}]
                set MeanRawFBFileName$flag \
                    [join "[lindex [split $file {.}] 0] . [lindex [split $file {.}] 1] .FBMeanRaw.sdds" {}]
                if {![file exist [set RegroupedFBFileName$flag]] || \
                        ![file exist [set HistogramFBFileName$flag]] || \
                        ![file exist [set MeanRawFBFileName$flag]]} {
                    return -code error "Self-test data file $file must be processed (or collected) before plotting."
                }
            }
        }
    }
    if {!$dataFlag && !$histFlag && !$averageFlag} {
        SetStatus "Select at least one of Data, Histogram, or Average to plot." 
        bell
        set dataFlag 1
        set histFlag 0
        set averageFlag 0
        return 0
    }
    SetStatus "Plotting self-test data file $SelfTestDataFileName with $CompareDataFileName ..."
    set sumscale 0
    if {$system=="SR"} {
        set sumscale 900
    }
    foreach flag {1 2} color {0 1} coord {0.05 0.5} {
        set stringOpt$flag "-string=@SelfTestNumberString,p=$coord,q=0.9,line=$color -string=@MSBoxAvgWtString,p=$coord,q=0.85,line=$color -string=@MultiplierString,p=$coord,q=0.8,line=$color -string=@GainModeString,p=$coord,q=0.76,line=$color"
    }
    if {$averageFlag} {
        set cols [exec sddsquery -col $MeanRawFileName1]
        set plotOpt "-labelsize=0.03 -layout=2,2  -enumeratedScales=interval=9 \
            -legend=file,edit=1Z-%/.MeanRaw.sdds//  -ylabel=edit=%/MeanRaw// \
            -graph=line,vary"
        set plotOpt1  "-labelsize=0.03 -layout=1,2  -enumeratedScales=interval=9 \
            -legend=file,edit=1Z-%/.MeanRaw.sdds//  -ylabel=edit=%/MeanRaw// \
            -graph=line,vary"
        set plotOpt2 "-labelsize=0.03 -layout=1,2  -enumeratedScales=interval=9 \
            -legend=file,edit=1Z-%/.FBMeanRaw.sdds//  -ylabel=edit=%/MeanRaw// \
            -graph=line,vary"
        foreach col $cols {
            if [string match "MeanRaw*X" $col] {
                lappend plotOpt \"-topline=BPM SCDU/Memory Scanner Raw X Position Data Averaged Over All Self-Tests\" 
                lappend plotOpt "-col=Rootname,$col $MeanRawFileName1 $stringOpt1"
                lappend plotOpt "-col=Rootname,$col $MeanRawFileName2 $stringOpt2"
                lappend plotOpt -end
                lappend plotOpt \"-topline=BPM SCDU/Memory Scanner Raw X Position Data Averaged Over All Self-Tests\" 
                lappend plotOpt "-col=BPMIndex,$col $MeanRawFileName1 $stringOpt1"
                lappend plotOpt "-col=BPMIndex,$col $MeanRawFileName2 $stringOpt2"
                lappend plotOpt -end
                regsub {X} $col Y col1
                lappend plotOpt \"-topline=BPM SCDU/Memory Scanner Raw Y Position Data Averaged Over All Self-Tests\"  
                lappend plotOpt "-col=Rootname,$col1 $MeanRawFileName1 $stringOpt1"
                lappend plotOpt "-col=Rootname,$col1 $MeanRawFileName2 $stringOpt2"
                lappend plotOpt -end
                lappend plotOpt \"-topline=BPM SCDU/Memory Scanner Raw Y Position Data Averaged Over All Self-Tests\"  
                lappend plotOpt "-col=BPMIndex,$col1 $MeanRawFileName1 $stringOpt1"
                lappend plotOpt "-col=BPMIndex,$col1 $MeanRawFileName2 $stringOpt2"
                lappend plotOpt -end
            }
            if [string match "MeanRaw*Sum" $col] {
                lappend plotOpt1 \"-topline=BPM SCDU/Memory Scanner Raw Sum Data Averaged Over All Self-Tests\"
                lappend plotOpt1 -scale=0,0,0,$sumscale 
                lappend plotOpt1 "-col=Rootname,$col $MeanRawFileName1 $stringOpt1"
                lappend plotOpt1 "-col=Rootname,$col $MeanRawFileName2 $stringOpt2"
                lappend plotOpt1 -end
                lappend plotOpt1 "-col=BPMIndex,$col $MeanRawFileName1 $stringOpt1"
                lappend plotOpt1 "-col=BPMIndex,$col $MeanRawFileName2 $stringOpt2"
                lappend plotOpt1 -end
            }
        }
        eval exec sddsplot [join $plotOpt] &
        eval exec sddsplot [join $plotOpt1] &

        if {$system=="SR" && $onlyAP2Flag1!=-1 && $onlyAP2Flag1!=-2} {
            foreach plane {x y} Plane {X Y} {
                lappend plotOpt2 \"-topline=Feedback BPM Memory Scanner Raw $Plane Position Data Averaged Over All Self-Tests\"
                lappend plotOpt2 "-col=Rootname,MeanRawFBMS$plane $MeanRawFBFileName1 $stringOpt1"
                lappend plotOpt2 "-col=Rootname,MeanRawFBMS$plane $MeanRawFBFileName2 $stringOpt2"
                lappend plotOpt2 -end
                lappend plotOpt2 \"-topline=Feedback BPM Memory Scanner Raw $Plane Position Data Averaged Over All Self-Tests\"
                lappend plotOpt2 "-col=BPMIndex,MeanRawFBMS$plane $MeanRawFBFileName1 $stringOpt1"
                lappend plotOpt2 "-col=BPMIndex,MeanRawFBMS$plane $MeanRawFBFileName2 $stringOpt2"
                lappend plotOpt2 -end
            }
            eval exec sddsplot [join $plotOpt2] &
        }
    }
    if {$histFlag} {
        set cols [exec sddsquery -col $HistogramFileName1]
      
        set plotOpt "-labelsize=0.03 -enumeratedScales=interval=9 \
            -legend=file,edit=1Z-%/.Hist.sdds//  -split=page -groupby=page -sep=page \
            -graph=line,vary -ylabel=edit=%/:Raw// "
        set plotOptX $plotOpt
        set plotOptY $plotOpt
        set plotOptSum $plotOpt
        foreach col $cols {
            if [string match ":Raw*Frequency" $col] {
                if [regexp {X} $col] {
                    set type X
                } elseif [regexp {Y} $col] {
                    set type Y
                } elseif [regexp {Sum} $col] {
                    set type Sum
                } else {
                    continue
                }
                lappend plotOpt$type \"-topline=BPM SCDU/Memory Scanner Raw $type Position Data Histograms\"
                lappend plotOpt$type "-col=RawCounts,$col $HistogramFileName1 $stringOpt1"
                lappend plotOpt$type "-string=@Rootname,p=0.05,q=0.70,line=0"
                lappend plotOpt$type "-col=RawCounts,$col $HistogramFileName2 $stringOpt2"
                lappend plotOpt$type "-string=@Rootname,p=0.5,q=0.70,line=1"
                lappend plotOpt$type -end
            }
        }
        eval exec sddsplot [join $plotOptX] &
        eval exec sddsplot [join $plotOptY] &
        eval exec sddsplot [join $plotOptSum] &
        
        if {$system=="SR" && $onlyAP2Flag1!=-1 && $onlyAP2Flag1!=-2} {
            eval exec sddsplot $plotOpt \
                \"-topline=Feedback BPM Memory Scanner Raw X Position Data Histogram\" \
                -col=RawCounts,:RawFBMSxFrequency $HistogramFBFileName1 $stringOpt1 \
                -col=RawCounts,:RawFBMSxFrequency $HistogramFBFileName2 $stringOpt2 &
            eval exec sddsplot $plotOpt \
                \"-topline=Feedback BPM Memory Scanner Raw Y Position Data Histogram\" \
                -col=RawCounts,:RawFBMSyFrequency $HistogramFBFileName1 $stringOpt1 \
                -col=RawCounts,:RawFBMSyFrequency $HistogramFBFileName2 $stringOpt2 &
            
        }
    }
    if {$dataFlag} {
        set cols [exec sddsquery -col $RegroupedFileName1]
      
        set plotOpt "-labelsize=0.03 -enumeratedScales=interval=9 \
            -legend=file,edit=1Z-%/.FBReg.sdds//%/.Reg.sdds//  -split=page -groupby=page -sep=page \
            -graph=line,vary -ylabel=edit=%/:Raw//"
        set plotOptX $plotOpt
        set plotOptY $plotOpt
        set plotOptSum $plotOpt
        foreach col $cols {
            if [string match ":Raw*" $col] {
                if [regexp {X} $col] {
                    set type X
                } elseif [regexp {Y} $col] {
                    set type Y
                } elseif [regexp {Sum} $col] {
                    set type Sum
                } else {
                    continue
                }
                lappend plotOpt$type \"-topline=BPM SCDU/Memory Scanner Raw $type Position vs. Self-Test Number\"
                lappend plotOpt$type "-col=SelfTestNumberIndex,$col $RegroupedFileName1 $stringOpt1" 
                lappend plotOpt$type "-col=SelfTestNumberIndex,$col $RegroupedFileName2 $stringOpt2" 
                lappend plotOpt$type -end
            }
        }
        eval exec sddsplot [join $plotOptX] &
        eval exec sddsplot [join $plotOptY] &
        eval exec sddsplot [join $plotOptSum] &
        
        if {$system=="SR" && $onlyAP2Flag1!=-1 && $onlyAP2Flag1!=-2} {
            eval exec sddsplot $plotOpt \
                \"-topline=Feedback BPM Memory Scanner Raw X Position vs Self-Test Number\" \
                -col=SelfTestNumberIndex,:RawFBMSx $RegroupedFBFileName1 $stringOpt1 \
                -col=SelfTestNumberIndex,:RawFBMSx $RegroupedFBFileName2 $stringOpt2 &
            
            eval exec sddsplot $plotOpt \
                \"-topline=Feedback BPM Memory Scanner Raw Y Position vs Self-Test Number\" \
                -col=SelfTestNumberIndex,:RawFBMSy $RegroupedFBFileName1 $stringOpt1 \
                -col=SelfTestNumberIndex,:RawFBMSy $RegroupedFBFileName2 $stringOpt2 &
        }
    }
}

# Plot out the results of a given self-test data file.  Returns 0 if the required processed data files do not 
# exist or all plotting flags are set to 0.  and gives an error message.  Returns 1 if the processed data files 
# exist and plots the results.
# Before returning, the procedure sets the plot request flags to their default.

proc PlotBPMSelfTestData {args} {

    global SelfTestDataFileRootName SelfTestDataFileName system
    global dataFlag histFlag averageFlag

    APSParseArguments {statusCallback}

    set fileIndex [lindex [split $SelfTestDataFileName {.}] 1]
    set CurrentSelfTestDataFileRootName [lindex [split $SelfTestDataFileName {.}] 0]

    set SelfTestRegroupedDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .Reg.sdds" {}]
    set SelfTestHistogramDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .Hist.sdds" {}]
    set SelfTestMeanRawDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .MeanRaw.sdds" {}]
    
    if {$system=="SR"} {
        # Check to see that the file contains more bpm pvs than the A:P2s.  The A:P2s do not have feedback PVs
        # defined so the following processing would generate an error.
        
        set colList [APSGetSDDSNames -fileName $SelfTestDataFileName -class column]
        set onlyAP2Flag [lsearch -glob $colList *FBMS*]
        
        if {${onlyAP2Flag}!=-1} {
            set SelfTestRegroupedFBDataFileName \
                [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBReg.sdds" {}]
            set SelfTestHistogramFBDataFileName \
                [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBHist.sdds" {}]
            set SelfTestMeanRawFBDataFileName \
                [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBMeanRaw.sdds" {}]
        }
    }
    if {!$dataFlag && !$histFlag && !$averageFlag} {
        if {$statusCallback!=""} {
            $statusCallback "Select at least one of Data, Histogram, or Average to plot."
        }       
        bell
        set dataFlag 1
        set histFlag 0
        set averageFlag 0
        return 0
    }
    
    if {[glob -nocomplain $CurrentSelfTestDataFileRootName.${fileIndex}.Reg.sdds]=="" ||
        [glob -nocomplain $CurrentSelfTestDataFileRootName.${fileIndex}.Hist.sdds]=="" ||
        [glob -nocomplain $CurrentSelfTestDataFileRootName.${fileIndex}.MeanRaw.sdds]==""} {
        if {$statusCallback!=""} {
            $statusCallback "Self-test data file $SelfTestDataFileName must be processed\n(or collected) \
                                         before plotting."
        }       
        bell
        set dataFlag 1
        set histFlag 0
        set averageFlag 0
        bell        
        return 0
    }
    
    if {$statusCallback!=""} {
        $statusCallback "Plotting self-test data file $SelfTestDataFileName..."
    }
    set sumscale 0
    if {$system=="SR"} {
        set sumscale 900
    }
    if {$averageFlag} {
        set filenameString [file tail $SelfTestMeanRawDataFileName]
        catch {exec sddsplot -labelsize=0.03 -layout=4,4  "-title=${filenameString}" \
                   -legend=yname,edit=%/MeanRaw// \
                   -graph=line,vary $SelfTestMeanRawDataFileName \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   "-topline=BPM SCDU/Memory Scanner Raw X Position Data Averaged Over All Self-Tests" \
                   -enumeratedScales=interval=9 \
                   "-ylabel=MeanRawCounts" \
                   -col=Rootname,MeanRaw*X \
                   -end \
                   -col=BPMIndex,MeanRaw*X \&}
        
        set filenameString [file tail $SelfTestMeanRawDataFileName]
        catch {exec sddsplot -labelsize=0.03 -layout=4,4 "-title=${filenameString}" \
                   -legend=yname,edit=%/MeanRaw// \
                   -graph=line,vary $SelfTestMeanRawDataFileName \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   "-topline=BPM SCDU/Memory Scanner Raw Y Position Data Averaged Over All Self-Tests" \
                   "-ylabel=MeanRawCounts" \
                   -enumeratedScales=interval=9 \
                   -col=Rootname,MeanRaw*Y \
                   -end \
                   -col=BPMIndex,MeanRaw*Y \&}
        set filenameString [file tail $SelfTestMeanRawDataFileName]
        catch {exec sddsplot -labelsize=0.03 -layout=4,4  "-title=${filenameString}" \
                   -legend=yname,edit=%/MeanRaw// \
                   -graph=line,vary $SelfTestMeanRawDataFileName \
                   -scale=0,0,0,$sumscale \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   "-topline=BPM SCDU/Memory Scanner Raw Sum Data Averaged Over All Self-Tests" \
                   "-ylabel=MeanRawCounts" \
                   -enumeratedScales=interval=9 \
                   -col=Rootname,MeanRaw*Sum \
                   -end \
                   -col=BPMIndex,MeanRaw*Sum \&}
        if {$system=="SR" && ${onlyAP2Flag}!=-1} {
            set filenameString [file tail $SelfTestMeanRawFBDataFileName]
            catch {exec sddsplot -layout=4,4 -labelsize=0.03 "-title=${filenameString}" -legend=yname,edit=%/MeanRaw// \
                       -graph=line,vary $SelfTestMeanRawFBDataFileName \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                       -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       "-topline=Feedback BPM Memory Scanner Raw X Position Data Averaged Over All Self-Tests" \
                       -enumeratedScales=interval=9 \
                       "-ylabel=MeanRawCounts" \
                       -col=Rootname,MeanRawFBMSx \
                       -end \
                       -col=BPMIndex,MeanRawFBMSx \&}
            
            set filenameString [file tail $SelfTestMeanRawFBDataFileName]
            catch {exec sddsplot -layout=4,4  -labelsize=0.03 "-title=${filenameString}" -legend=yname,edit=%/MeanRaw// \
                       -graph=line,vary $SelfTestMeanRawFBDataFileName \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                     -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       "-topline=Feedback BPM Memory Scanner Raw Y Position Data Averaged Over All Self-Tests" \
                       "-ylabel=MeanRawCounts" \
                       -enumeratedScales=interval=9 \
                       -col=Rootname,MeanRawFBMSy \
                       -end \
                       -col=BPMIndex,MeanRawFBMSy \&}
        }
    }
    
    if {$histFlag} {
        set filenameString [file tail $SelfTestHistogramDataFileName]
        catch {exec sddsplot -layout=4,4  -labelsize=0.03 -legend=yname,edit=%/Frequency//%/:Raw// \
                 -split=page -groupby=page -sep=page "-title=@Rootname" \
                 -graph=line,vary $SelfTestHistogramDataFileName \
                 -col=RawCounts,:Raw*XFrequency \
                 -string=@SelfTestNumberString,p=0.05,q=0.9 \
                 -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                 -string=@MultiplierString,p=0.05,q=0.8 \
                 -string=@GainModeString,p=0.05,q=0.76 \
                 -string=${filenameString},p=0.05,q=0.70 \
                 "-topline=BPM SCDU/Memory Scanner Raw X Position Data Histograms" \
                 "-ylabel=Frequency" \&}

        catch {exec sddsplot -labelsize=0.03 -legend=yname,edit=%/Frequency//%/:Raw// \
                 -split=page -groupby=page -sep=page "-title=@Rootname" \
                 -graph=line,vary $SelfTestHistogramDataFileName \
                 -col=RawCounts,:Raw*YFrequency \
                 -string=@SelfTestNumberString,p=0.05,q=0.9 \
                 -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                 -string=@MultiplierString,p=0.05,q=0.8 \
                 -string=@GainModeString,p=0.05,q=0.76 \
                 -string=${filenameString},p=0.05,q=0.70 \
                 "-topline=BPM SCDU/Memory Scanner Raw Y Position Data Histograms" \
                 "-ylabel=Frequency" \&}

        catch {exec sddsplot -labelsize=0.03 -layout=4,4  -legend=yname,edit=%/Frequency//%/:Raw// \
                 -split=page -groupby=page -sep=page "-title=@Rootname" \
                 -graph=line,vary $SelfTestHistogramDataFileName \
                 -col=RawCounts,:Raw*SumFrequency \
                 -string=@SelfTestNumberString,p=0.05,q=0.9 \
                 -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                 -string=@MultiplierString,p=0.05,q=0.8 \
                 -string=@GainModeString,p=0.05,q=0.76 \
                 -string=${filenameString},p=0.05,q=0.70 \
                 "-topline=BPM SCDU/Memory Scanner Raw Sum Data Histograms" \
                 "-ylabel=Frequency" \&}
        
        if {$system=="SR" && ${onlyAP2Flag}!=-1} {        
            set filenameString [file tail $SelfTestHistogramFBDataFileName]
            catch {exec sddsplot -labelsize=0.03 -layout=4,4  -legend=yname,edit=%/Frequency//%/:Raw// \
                       -split=page -groupby=page -sep=page "-title=@Rootname" \
                       -graph=line,vary $SelfTestHistogramFBDataFileName \
                       -col=RawCounts,:RawFBMSxFrequency \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                       -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       -string=${filenameString},p=0.05,q=0.70 \
                       "-topline=Feedback BPM Memory Scanner Raw X Position Data Histogram" \
                       "-ylabel=Frequency" \&}
            
            catch {exec sddsplot -labelsize=0.03 -layout=4,4  -legend=yname,edit=%/Frequency//%/:Raw// \
                       -split=page -groupby=page -sep=page "-title=@Rootname" \
                       -graph=line,vary $SelfTestHistogramFBDataFileName \
                       -col=RawCounts,:RawFBMSyFrequency \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                       -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       -string=${filenameString},p=0.05,q=0.70 \
                       "-topline=Feedback BPM Memory Scanner Raw Y Position Data Histogram" \
                       "-ylabel=Frequency" \&}
        }
    }
    
    if {$dataFlag} {
        set filenameString [file tail $SelfTestRegroupedDataFileName]
	set clip 0
	if {$system=="SR"} {
	    set clip 5
            #do not clip if the data points is too less
            set rows [lindex [exec sdds2stream -rows=bare $SelfTestRegroupedDataFileName] 0]
            if {$rows<=10} {
                set clip 0
            }
        }
        catch {exec sddsplot -labelsize=0.03 -layout=4,4  -clip=$clip,$clip -legend=yname,edit=%/:Raw// \
                   -split=page -groupby=page -sep=page "-title=@Rootname" \
                   -graph=line,vary $SelfTestRegroupedDataFileName \
                   -col=SelfTestNumberIndex,:Raw*X \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   -string=${filenameString},p=0.05,q=0.70 \
                   "-topline=BPM SCDU/Memory Scanner Raw X Position vs Self-Test Number" \
                   "-ylabel=RawCounts" &} result
        
        catch {exec sddsplot -labelsize=0.03 -layout=4,4  -clip=$clip,$clip -legend=yname,edit=%/:Raw// \
                   -split=page -groupby=page -sep=page "-title=@Rootname" \
                   -graph=line,vary $SelfTestRegroupedDataFileName \
                   -col=SelfTestNumberIndex,:Raw*Y \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   -string=${filenameString},p=0.05,q=0.70 \
                   "-topline=BPM SCDU/Memory Scanner Raw Y Position vs Self-Test Number" \
                   "-ylabel=RawCounts" &} result
      
        catch {exec sddsplot -labelsize=0.03 -layout=4,4  -clip=$clip,$clip -scale=0,0,0,$sumscale \
                   -legend=yname,edit=%/:Raw// \
                   -split=page -groupby=page -sep=page "-title=@Rootname" \
                   -graph=line,vary $SelfTestRegroupedDataFileName \
                   -col=SelfTestNumberIndex,:Raw*Sum \
                   -string=@SelfTestNumberString,p=0.05,q=0.9 \
                   -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                   -string=@MultiplierString,p=0.05,q=0.8 \
                   -string=@GainModeString,p=0.05,q=0.76 \
                   -string=${filenameString},p=0.05,q=0.70 \
                   "-topline=BPM SCDU/Memory Scanner Raw Sum Data vs Self-Test Number" \
                   "-ylabel=RawCounts" &} result
        
        if {$system=="SR" && ${onlyAP2Flag}!=-1} {
            set filenameString [file tail $SelfTestRegroupedFBDataFileName]
            set clip 5
            set rows [lindex [exec sdds2stream -rows=bare $SelfTestRegroupedFBDataFileName] 0]
            if {$rows<=10} {
                set clip 0
            }
            catch {exec sddsplot -labelsize=0.03 -layout=4,4  -clip=$clip,$clip -legend=yname,edit=%/:Raw// \
                       -split=page -groupby=page -sep=page "-title=@Rootname" \
                       -graph=line,vary $SelfTestRegroupedFBDataFileName \
                       -col=SelfTestNumberIndex,:RawFBMSx \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                       -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       -string=${filenameString},p=0.05,q=0.70 \
                       "-topline=Feedback BPM Memory Scanner Raw X Position vs Self-Test Number" \
                       "-ylabel=RawCounts" \&}
            
            catch {exec sddsplot -labelsize=0.03 -layout=4,4  -clip=$clip,$clip -legend=yname,edit=%/:Raw// \
                       -split=page -groupby=page -sep=page "-title=@Rootname" \
                       -graph=line,vary $SelfTestRegroupedFBDataFileName \
                       -col=SelfTestNumberIndex,:RawFBMSy \
                       -string=@SelfTestNumberString,p=0.05,q=0.9 \
                       -string=@MSBoxAvgWtString,p=0.05,q=0.85 \
                       -string=@MultiplierString,p=0.05,q=0.8 \
                       -string=@GainModeString,p=0.05,q=0.76 \
                       -string=${filenameString},p=0.05,q=0.70 \
                       "-topline=Feedback BPM Memory Scanner Raw Y Position vs Self-Test Number" \
                       "-ylabel=RawCounts" \&}
            
        }
    }
    
    if {$statusCallback!=""} {
        $statusCallback "Plotting for data file $SelfTestDataFileName completed."
    }
    set dataFlag 1
    set histFlag 0
    set averageFlag 0
    return 1
}


# This procedure removes processed data files (*Reg*, *Hist*, and *MeanRaw*) for a given self-test measurement.
# Returns 0 if no such files are found, returns 1 after removing the files.

proc CleanupProcessedBPMDataFiles {args} {

    global SelfTestDataFileRootName SelfTestDataFileName

    APSParseArguments {statusCallback}

    set fileIndex [lindex [split $SelfTestDataFileName {.}] 1]
    
    set SelfTestRegroupedDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .Reg.sdds" {}]
    set SelfTestHistogramDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .Hist.sdds" {}]
    set SelfTestMeanRawDataFileName \
      [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
      [lindex [split $SelfTestDataFileName {.}] 1] .MeanRaw.sdds" {}]

    # Check to see that the file contains more bpm pvs than the A:P2s.  The A:P2s do not have feedback PVs
    # defined so the following processing would generate an error.

    set colList [APSGetSDDSNames -fileName ${SelfTestDataFileName} -class column]
    set onlyAP2Flag [lsearch -glob $colList *FBMS*]

    if {${onlyAP2Flag}!=-1} {
        set SelfTestRegroupedFBDataFileName \
          [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBReg.sdds" {}]
        set SelfTestHistogramFBDataFileName \
          [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBHist.sdds" {}]
        set SelfTestMeanRawFBDataFileName \
          [join "[lindex [split $SelfTestDataFileName {.}] 0] . \
          [lindex [split $SelfTestDataFileName {.}] 1] .FBMeanRaw.sdds" {}]
    }

    if {$statusCallback!=""} {
        $statusCallback "Deleting processed files and sddsmonitor input file for data file \
                                 $SelfTestDataFileName..."
    }
    
    if {[glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.Reg.sdds]=="" && 
        [glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.Hist.sdds]=="" && 
        [glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.MeanRaw.sdds]==""} {
        if {$statusCallback!=""} {
            $statusCallback "No processed files and/or sddsmonitor input file found for \
                                         $SelfTestDataFileName."
        }
        bell
        return 0
    }

    catch {file delete $SelfTestRegroupedDataFileName $SelfTestHistogramDataFileName \
             $SelfTestMeanRawDataFileName}
    
    if {${onlyAP2Flag}!=-1} {

        if {[glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.FBReg.sdds]=="" &&
            [glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.FBHist.sdds]=="" &&
            [glob -nocomplain $SelfTestDataFileRootName.${fileIndex}.FBMeanRaw.sdds]==""} {
            if {$statusCallback!=""} {
                $statusCallback "No processed feedback files and/or sddsmonitor input file found for \
                                         $SelfTestDataFileName."
            }
            bell
            return 0
        }
    }

    catch {file delete $SelfTestRegroupedFBDataFileName $SelfTestHistogramFBDataFileName \
             $SelfTestMeanRawFBDataFileName}
    
    if {$statusCallback!=""} {
        $statusCallback "Processed data files and/or sddsmonitor input file for $SelfTestDataFileName deleted."
    }

    bell
    return 1
}

# Procedure to update data file contents description.  Returns 1 when completed.
# Returns 0 if file does not exists.

proc UpdateDataFileContents {args} {

    global SelfTestDataFileName directory contentsString
    APSParseArguments {statusCallback}

    if {![file exists $SelfTestDataFileName]} {
        if {$statusCallback!=""} {
            $statusCallback "Please select an existing self-test data file."
        }
        bell
        return 0
    }

    if [catch {exec sddsprocess $SelfTestDataFileName ${directory}/tmpFile -reprint=param,Contents,[APSMakeSafeQualifierString $contentsString]
        exec gzip ${directory}/tmpFile
        eval file delete ${SelfTestDataFileName} ${directory}/tmpFile
        file rename ${directory}/tmpFile.gz $SelfTestDataFileName} result] {
        return -code error "$result"
    }
    
    if {$statusCallback!=""} {
        $statusCallback "File $SelfTestDataFileName contents string updated."
    }
    return 1
}

# Procedure to set the abortFlag to 1 when the abort button is pressed.  It also sets the processFlag to 0 in 
# case the loop is hung up on the tkwait command with processFlag stuck at a value of 1.
# returns 1 when completed

proc SetFlagsOnAbort {} {

    global abortFlag processFlag

    set abortFlag 1

    if {$processFlag==1} {
        set processFlag 0
    } elseif {$processFlag==0} {
        set processFlag 1
    } elseif {processFlag==-1} {
        set processFlag 0
    }
    return 1
}

#execution starts here
set system SR
set args $argv
APSStrictParseArguments {system}

switch $system {
    SR {
        set suffixList {:RawSCDUX :RawSCDUY :RawSCDUSum :RawMSX :RawMSY :RawMSSum :RawMSAvgX :RawMSAvgY}
    }
    Booster {
        set suffixList {:RawSCDUX :RawSCDUY :RawSCDUSum :SCDUX :SCDUY :PositionX :PositionY}
    }
    default {
        puts stderr "Invalid system - $system provided, it has to be SR or Booster."
        exit 
    }
}
set directory [set ${system}Directory]

MakeSRBPMCheckoutStatusWidget .userFrame  -system $system

set sectorCount 40
set orient horizontal
set fileWidth 80
set labelList $bpmList
if {$system=="Booster"} {
    set bpmList {C0P1 C0P2 C1P1 C1P2 C2P1 C2P2 C3P1 C3P2 C4P1 \
                     C4P2 C5P1 C5P2 C6P1 C6P2 C7P1 C7P2 C8P1 C8P2 C9P1 C9P2}
    set sectorCount 4
    set orient vertical
    regsub -all {C} $bpmList "" labelList
}

APSSRSectorButtons .bpmButtons -parent .userFrame -rootname bpm \
  -orientation $orient -sectorCount $sectorCount \
  -label "$system BPM Selections" -description "$system BPM Selections" \
  -sectorControl 1 \
  -itemList $bpmList -packOption "-side top" \
  -itemLabelList $labelList 

MakeLabelledEntryWidgets .labelledEntries -parent .userFrame -fileWidth $fileWidth
MakeSRBPMSelfTestWidget .selfTestWidgets -parent .userFrame -system $system

# Local Variables:
# mode: tcl
# End:
