#
# $Log: not supported by cvs2svn $
# Revision 1.31  2010/08/25 21:49:19  shang
# modified to not collecting old beam history for FPGA bpms.
#
# Revision 1.30  2010/02/16 16:13:13  shang
# set the excludedSectors to be FPGA bpm sectors to avoid collecting beam history of FPGA bpms because the corresponding BPLD trip and beam history PVs do not exist.
#
# Revision 1.29  2004/06/11 16:32:03  soliday
# Modified calls to APSSRSetFifoFillModes related to the S[1-40][AB]:P1:bh.FIM0
# PVs that no longer exist.
#
# Revision 1.28  2004/06/11 16:19:55  soliday
# Updated to reflect the fact that the S[1-40][AB]:P1:bh.FIM0 PVs no longer
# exist.
#
# Revision 1.27  2003/07/02 19:20:26  soliday
# APSSRGetTrippedBeamHistory should now be slightly faster.
#
# Revision 1.26  2002/09/03 19:11:54  emery
# Removed extraneous puts stderr in last few versions.
#
# Revision 1.25  2002/09/03 19:10:37  emery
# Correct use of bpm name variable for the gain PV.
# Added comments which explain the various variables
# that contain the bpm name.
#
# Revision 1.24  2002/09/03 18:53:00  emery
# Added gainString as parameter to bpm history file.
#
# Revision 1.23  2002/08/30 19:25:01  emery
# Added collection and recording of scdu Gain value for bpm
# histories.
#
# Revision 1.22  2001/08/25 03:12:34  emery
# Replaced exec rm with file delete.
#
# Revision 1.21  2001/04/12 05:54:06  emery
# Use the Channel[12]History columns from the file
# /home/helios/oagData/sr/BPLDs/sectors.sdds
# This allows the record of a different bpm if some
# bpld uses a P0 bpm or a replacement for a bad history.
#
# Revision 1.20  2001/02/22 14:33:10  borland
# Removed sectors 15 and 16 from excluded list for tripped beam histories.
#
# Revision 1.19  2000/05/11 01:00:33  emery
# Sector 9 bpld bpms no longer forced for data collection.
#
# Revision 1.18  1999/11/30 15:44:50  borland
# Sector 9 BPLD BPM data is now collected by APSSRCollectTrippedBeamHistories
# even if that BPLD didn't trip.  For diagnostic purposes due to BPM problems.
#
# Revision 1.17  1999/09/16 23:27:57  emery
# Added P1 to the list of fifos to control.
#
# Revision 1.16  1999/09/16 23:25:52  emery
# Procedure APSSRCollectTrippedBeamHistories can now deal with
# BPLDs that are connected to either P1 or P2 using channel info
# from file/home/helios/oagData/sr/BPLDs/sectors.sdds
#
# Revision 1.15  1999/09/07 16:36:44  emery
# Added procedure APSSRSetFifoResync, a procedure similar to
# APSSRSetFifoFillModes, to change the state of the resync
# PV of the bpm history fifo.
#
# Revision 1.14  1997/11/03 18:01:03  borland
# Added a statement to remove intermediate beam history files when
# "minimal data" is requested.
#
# Revision 1.13  1997/09/17 20:03:09  borland
# Added -minimalData option to allow saving only of index, position,
# and sum signal.
#
# Revision 1.12  1997/07/28 04:41:13  borland
# Added ability to exclude a list of sectors (in case of hardware problems,
# for example).
#
# Revision 1.11  1997/04/18 18:02:45  borland
# APSSRGetTrippedBeamHistory: Removed an unnecessary test for existence
# of raw file.  Added code to wait for file to finish being written.
#
# Revision 1.10  1997/03/04 15:15:59  borland
# Added -doGzip option to allow gzipping data files as they are taken.
#
# Revision 1.9  1996/12/16 16:41:12  borland
# Increased sleep times after some statements in the hope this will resolve
# problems with empty data files.
#
# Revision 1.8  1996/12/06 14:38:22  borland
# Added -forceAll feature.
#
# Revision 1.7  1996/09/27 19:21:41  borland
# Added useStopOnFull option to APSSRCollectTrippedBeamHistories.  Default
# behavior is not to emply stop on full mode of histories.
#
# Revision 1.6  1996/09/24 23:40:13  borland
# Switch from logging P1's to P2's in tripped sectors.
#
# Revision 1.5  1996/09/24 23:05:31  borland
# Fixed a bug (was trying to remove the wrong file).
#
# Revision 1.4  1996/09/24 22:48:57  borland
# Corrected a typo introduced in the previous change.
#
# Revision 1.3  1996/09/24 22:46:53  borland
# Now only sets Stop on Full mode for A:P2, B:P2, and B:P5 BPMs.
#
# Revision 1.2  1996/09/24 21:31:23  borland
# Now remove raw data file.
#
# Revision 1.1  1996/09/24 21:17:55  borland
# First version.
#
#

set apsSRBPMNameArray(1) A:P1
set apsSRBPMNameArray(2) A:P2
set apsSRBPMNameArray(3) A:P3
set apsSRBPMNameArray(4) A:P4
set apsSRBPMNameArray(5) B:P5
set apsSRBPMNameArray(6) B:P4
set apsSRBPMNameArray(7) B:P3
set apsSRBPMNameArray(8) B:P2
set apsSRBPMNameArray(9) B:P1

# main procedure that is called from other applications
proc APSSRCollectTrippedBeamHistories {args} {
    #These PVs no longer exist
    return
    # collect "relevant" beam history data after a trip
    set namePrefix ""
    set nameSuffix ""
    set statusCallback "puts stderr"
    set useStopOnFull 0
    set forceAll 0
    set doGzip 0
    set minimalData 0

    # list of sectors to exclude (e.g., for hardware reasons)
    set excludeSectors [APSGetFPGASectorList]

    APSStrictParseArguments {namePrefix nameSuffix statusCallback useStopOnFull forceAll doGzip \
                           minimalData}
    if {![string length $nameSuffix] && ![string length $namePrefix]} {
        return -code error "APSSRCollectTrippedBeamHistories: supply nameSuffix and/or namePrefix"
    }

    if [catch {APSSRGetTrippedBPLDList -forceAll $forceAll} trippedSectorList] {
        return -code error "APSSRCollectTrippedBeamHistories: $trippedSectorList"
    }

    if $useStopOnFull {
        # put BPMs FIFO's in stop on full mode
        if [catch {APSSRSetFifoFillModes -mode "Stop on Full" -BPMList {A:P2 B:P2 B:P5}} result] {
            return -code error "APSSRCollectTrippedBeamHistories: $result"
        }
    }

    set problemBPMList ""
    set BPLDFile /home/helios/oagData/sr/BPLDs/sectors.sdds
    if [catch {sdds load $BPLDFile BPLDConfig} result] {
        return -code error "APSSRCollectTrippedBeamHistories: loading $BPLDFile: $result"
    }
    # index 0 means take data from first page. (it's the only page anyway)
    set BPLDList [lindex $BPLDConfig(Column.Sector) 0]
    set Channel1  [lindex $BPLDConfig(Column.Channel1History) 0]
    set Channel2  [lindex $BPLDConfig(Column.Channel2History) 0]
    foreach sector $BPLDList chan1 $Channel1 chan2 $Channel2 {
        set firstChannelBPM($sector) B:$chan1
        set secondChannelBPM($sector) A:$chan2
    }
    set sectorsDone 0
    foreach sector $trippedSectorList {
        if [lsearch -exact $excludeSectors $sector]!=-1 continue
        set bpmName(0) $firstChannelBPM($sector)
        set bpmName(1) $secondChannelBPM($sector)
        for {set sectorOffset 0} {$sectorOffset<2} {incr sectorOffset} {
            set sector1 [expr $sector+$sectorOffset]
            if [lsearch -exact $excludeSectors $sector1]!=-1 continue
            if [catch {APSSRGetTrippedBeamHistory -sector [expr $sector+$sectorOffset] \
                         -BPMName $bpmName($sectorOffset) -doGzip $doGzip -minimalData $minimalData \
                         -namePrefix ${namePrefix}S[expr $sector+$sectorOffset]$bpmName($sectorOffset) \
                         -nameSuffix $nameSuffix} result] {
                if [string length $statusCallback] {
                    eval $statusCallback {"$result"}
                }
                lappend problemBPMList S[expr $sector+$sectorOffset]$bpmName($sectorOffset) 
            } else {
                if [string length $statusCallback] {
                    eval $statusCallback {"Took data for S[expr $sector+$sectorOffset]$bpmName($sectorOffset) into files $result"}
                }
                incr sectorsDone
            }
        }
    }
    
    # collect some BP5 data
    foreach sector {1 2 3 4 5} {
        if [lsearch -exact $excludeSectors $sector]!=-1 continue
        if [catch {APSSRGetTrippedBeamHistory -sector $sector -BPMName B:P5 \
                     -doGzip $doGzip -minimalData $minimalData \
                     -namePrefix ${namePrefix}S${sector}B:P5 -nameSuffix $nameSuffix} result] {
            if [string length $statusCallback] {
                eval $statusCallback {"$result"}
            }
            lappend problemBPMList S${sector}B:P5
        } else {
            if [string length $statusCallback] {
                eval $statusCallback {"Took data for S${sector}B:P5 into files $result"}
            }
            incr sectorsDone
        }
    }

    if $useStopOnFull {
        # put BPMs FIFO's in continuous fill mode
        if [catch {APSSRSetFifoFillModes -mode "Continuous Fill" -BPMList {A:P2 B:P2 B:P5}} result] {
            return -code error "APSSRCollectTrippedBeamHistories: $result"
        }
    }

    return -code ok [list $sectorsDone [llength $problemBPMList] [join $problemBPMList ,]]
}

proc APSSRSetFifoFillModes {args} {
    #These PVs no longer exist
    return
    set mode "none-given"
    lappend BPMList A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2
    APSStrictParseArguments {mode BPMList}

    if [string length $mode]>1 {
        switch $mode {
            "Continuous Fill" {
                set mode 0
            } 
            "Stop on Full" {
                set mode 1
            }
            default {
                return -code error "APSSRSetFifoFillModes: unknown mode: $mode"
            }
        }
    }
    if [catch {exec cavput -blunderAhead=silently -pend=30 \
                 -list=S -range=beg=1,end=40 -list=[join $BPMList ,] \
                 -list=:bh.FIM0=$mode} result] {
        return -code error "APSSRSetFifoFillModes: $result"
    }
}

proc APSSRSetFifoResync {args} {
    #These PVs no longer exist
    return
    set state "none-given"
    lappend BPMList A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2
    APSStrictParseArguments {state BPMList}

    if [string length $state]>1 {
        switch $state {
            "Disable" {
                set state 0
            } 
            "Enable" {
                set state 1
            }
            default {
                return -code error "APSSRSetFifoResync: unknown state: $state"
            }
        }
    }
    if [catch {exec cavput -blunderAhead=silently -pend=30 \
                 -list=S -range=beg=1,end=40 -list=[join $BPMList ,] \
                 -list=:bh.FIR0=$state} result] {
        return -code error "APSSRSetFifoResync: $result"
    }
}


proc APSSRGetTrippedBPLDList {args} {
    set forceAll 0
    APSStrictParseArguments {forceAll}
    set excludeSectors [APSGetFPGASectorList]
    # get list of BPLDs in use.
    if {[catch {APSGetSDDSColumn -fileName /home/helios/oagData/sr/BPLDs/sectors.sdds \
                  -column Sector} sectorList] || [llength $sectorList]==0} {
        return -code error "APSSRGetTrippedBPLDList: no sector list for BPLDs!"
    }
    set sectorList1 ""
    foreach sector $sectorList {
        if [lsearch -exact $excludeSectors $sector]==-1 {
            lappend sectorList1 $sector
        }
    }
    if ![llength $sectorList1] {
        return -code ok
    }
    # get state of each BPLD
    if [catch {exec cavget -list=S -list=[join $sectorList1 ,] -list=BPLD:TripPendingCC} tripFlags] {
        return -code error "APSSRGetTrippedBPLDList: problem getting trip flags: $tripFlags"
    }

    set trippedSectors ""
    set index 0 
    foreach sector $sectorList1 {
        if {$forceAll || [lindex $tripFlags $index]} {
            lappend trippedSectors $sector
        }
        incr index
    }
    return -code ok $trippedSectors
}

proc APSSRGetTrippedBeamHistory {args} {
    #These PVs no longer exist
    return
    # collect MOMBO beam history assuming that the beam just tripped and
    # that BPMs were set up properly (e.g,. continuous fill mode)

    global apsSRBPMNameArray
    set sector 0
    set BPMNumber 0
    set BPMName ""
    set namePrefix ""
    set nameSuffix ""
    set doGzip 0
    set minimalData 0
    APSStrictParseArguments {sector BPMNumber BPMName namePrefix nameSuffix doGzip minimalData}

    if [string length $namePrefix]==0 {
        return -code error "APSSRGetTrippedBeamHistory: no namePrefix supplied"
    }
    if [string length $nameSuffix]==0 {
        return -code error "APSSRGetTrippedBeamHistory: no nameSuffix supplied"
    }

    set sector [format %ld $sector]
    if {$sector<1 || $sector>40} {
        return -code error "APSSRGetTrippedBeamHistory: sector out of range"
    }
    if ![string length $BPMName] {
        if $BPMNumber==0 {
            return -code error "APSSRGetTrippedBeamHistory: supply BPMNumber or BPMName"
        }
        if {$BPMNumber<1 || $BPMNumber>9} {
            return -code error "APSSRGetTrippedBeamHistory: BPMNumber out of range"
        }
        set BPMName $apsSRBPMNameArray($BPMNumber)
    } else {
        for {set BPMNumber 1} {$BPMNumber<10} {incr BPMNumber} {
            if [string compare $apsSRBPMNameArray($BPMNumber) $BPMName]==0 {
                break
            }
        }
        if {$BPMNumber==10} {
            return -code error "APSSRGetTrippedBeamHistory: BPMName not known"
        }
    }

    set PVroot S:bpm${sector}
    set fullBPMName S${sector}$BPMName

    # select desired BPM, set for single-shot mode, and enable data transfer
    if [catch \
          {exec cavput -list=$PVroot -list=:bh. -list=BPMI=[expr ($sector-1)*9+$BPMNumber-1],BRDM=0,BRDE=1} \
          result] {
        return -code error  "APSSRGetTrippedBeamHistory: cavput error: $result"
    }

    after 2000
    if [catch {exec cavput -list=$PVroot:bh.SSEN=1} result] {
        return -code error  "APSSRGetTrippedBeamHistory: cavput error: $result"
    }

    # record present time so we know if a file found in the directory
    # is a new one
    set timeNow [expr {[clock seconds] - 5}]
    if [catch {exec cavput -list=$PVroot:bh:writeFile_sub.PROC=1} result] {
        return -code error  "APSSRGetTrippedBeamHistory: cavput error: $result"
    }
    set file ""
    for {set try 0} {$try<60} {incr try} {
        after 1000
	if [catch {eval exec ls -t1 [glob /home/helios4/srbpm/pub/${fullBPMName}*] } files] {
	    set file ""
	    continue
	}
	set file [lindex $files 0]
        #if [catch {eval exec ls -t1 [glob /home/helios4/srbpm/pub/${fullBPMName}*] \
        #             | head -1 2> /dev/null} file] {
        #    continue
        #}
        if {![string length $file]} continue
        if {$timeNow<=[file mtime $file]} break
    }

    if ![string length $file] {
        return -code error  "APSSRGetTrippedBeamHistory: no file found for $fullBPMName"
    }
    
    if [catch {exec cavput -list=$PVroot:bh.BRDE=0} result] {
        return -code error  "APSSRGetTrippedBeamHistory: cavput error: $result"
    }

    # make sure the file size has stopped growing
    set size0 [file size $file]
    for {set try 0} {$try<10} {incr try} {
        after 2000
        set size1 [file size $file]
        if $size0==$size1 break
        set size1 $size0
    }

    if [catch {file copy $file .} result] {
        return -code error  "APSSRGetTrippedBeamHistory: file copy problem: $result"
    }

    set filename [file tail $file]
    if [catch {exec beamH2sdds $filename} result] {
        return -code error  "APSSRGetTrippedBeamHistory: beamH2sdds: $result"
    }

    if [catch {file delete $filename} result] {
        return -code error  "APSSRGetTrippedBeamHistory: unable to remove file $filename"
    }

    set dataRootname [file rootname $filename]
    # determine gain
    if [catch {exec cavget -list=${fullBPMName}:normal_bi -noQuotes \
                 -pend=10} gainString] {
        return -code error  "APSSRGetTrippedBeamHistory: unable to connect to gain PV: $gainString"
    }
    switch $gainString {
        "Hi Gain" {set gain 4}
        "Lo Gain" -
        default {set gain 1}
    }
    # variable fullBPMName is the bpm name with the style S1A:P1
    # dataRootname is of the style S1A:P1_020903-140243 with the added digits
    # a time stamp.
    # namePrefix is usually of the style <dir>/S1A:P1, with dir usually the dot
    # directory.
    if [catch {exec sddsprocess ${dataRootname}-x.sdds -noWarning \
                 -define=para,Gain,$gain \
                 -print=para,GainString,$gainString 
        exec sddsprocess ${dataRootname}-y.sdds -noWarning \
                 -define=para,Gain,$gain \
                 -print=para,GainString,$gainString
        file delete ${dataRootname}-x.sdds~ ${dataRootname}-y.sdds~ \
             } result] {
        return -code error  "APSSRGetTrippedBeamHistory: problem adding gain to files: $result"
    }
    if !$minimalData {
        if {[catch {file rename ${dataRootname}-x.sdds ${namePrefix}-x$nameSuffix} result] || \
              [catch {file rename ${dataRootname}-y.sdds ${namePrefix}-y$nameSuffix} result]} {
            return -code error  "APSSRGetTrippedBeamHistory: file rename problem: $result"
        }
    } else {
        if {[catch {exec sddsconvert -delete=column,xt,xsumt,xsums \
                      ${dataRootname}-x.sdds ${namePrefix}-x$nameSuffix} result] || \
              [catch {exec sddsconvert -delete=column,yt,ysumt,ysums \
                        ${dataRootname}-y.sdds ${namePrefix}-y$nameSuffix} result]} {
            return -code error  "APSSRGetTrippedBeamHistory: sddsconvert problem: $result"
        }
        catch {eval file delete ${dataRootname}-x.sdds ${dataRootname}-y.sdds}
    }
    if !$doGzip {
        return -code ok [list ${namePrefix}-x$nameSuffix ${namePrefix}-y$nameSuffix]
    } 
    if {[catch {exec gzip ${namePrefix}-x$nameSuffix} result] || \
          [catch {exec gzip ${namePrefix}-y$nameSuffix} result]} {
        return -code error  "APSSRGetTrippedBeamHistory: gzip problem: $result"
    }
    return -code ok [list ${namePrefix}-x$nameSuffix.gz ${namePrefix}-y$nameSuffix.gz]
}

