Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

gEvtCli.py

00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2002
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 ## \namespace evtCli
00011 ##
00012 ## \brief Event handler classes
00013 ##
00014 ##  Event objects:
00015 ##
00016 ##    The following list contains the objects populated during parsing.
00017 ##    Please refer to the individual classes to find out how to access
00018 ##    event data stored in these objects:
00019 ##
00020 ##    - CAL_LogAccepts   -- List of evCAL_LogAccepts
00021 ##
00022 ##    - CAL_LogData      -- List of evCAL_LayerLogData
00023 ##
00024 ##    - TKRstrips        -- List of evTKR_StripData
00025 ##
00026 ##    - TKRaccepts       -- List of int
00027 ##
00028 ##    - TKRtots          -- List of evTKR_TOTdata
00029 ##
00030 ##    - diag             -- evDiag_Data
00031 ##
00032 ##    - errSummary       -- evErr_Summary
00033 ##
00034 ##    - errGCCCmsg       -- List of evErr_GCCC_Message
00035 ##
00036 ##    - errGTCCmsg       -- List of evErr_GTCC_Message
00037 ##
00038 ##    - errCablePhase    -- evErr_CablePhase
00039 ##
00040 ##    - errCableTimeOut  -- evErr_CableTimeOut
00041 ##
00042 ##    - aem              -- AEM
00043 ##
00044 ##    - aem.PHA          -- Dictionary of evAEM_PHA indexed by cable number
00045 ##
00046 ##    - gem              -- GEM
00047 ##
00048 ##    - gem.vetoList     -- evGEM_Veto_List
00049 
00050 __facility__ = "Online"
00051 __abstract__ = "Event handler client"
00052 __author__   = "Selim Tuvi <stuvi@slac.stanford.edu> SLAC - GLAST I&T/Online"
00053 __date__     = ("$Date: 2005/09/01 01:50:56 $").split(' ')[1]
00054 __version__  = "$Revision: 2.37 $"
00055 __release__  = "$Name: R04-12-00 $"
00056 __credits__  = "SLAC"
00057 
00058 import LATTE.copyright_SLAC
00059 
00060 import          sys
00061 import          struct
00062 import          select
00063 import          traceback
00064 import logging  as     log
00065 from string     import *
00066 from os         import *
00067 from time       import sleep, time, gmtime, asctime
00068 from operator   import isNumberType
00069 from math       import modf
00070 
00071 from gLog import logStack, logException
00072 from gException import LATInterfaceStatus, LATInterfaceException
00073 from gBits import BitField, q, dump_cells
00074 from gSocket import Socket
00075 from gOpcode import Opcode
00076 
00077 
00078 N_GCCC =  4
00079 N_GCRC =  4
00080 N_GCFE = 12
00081 
00082 N_GTCC =  8
00083 N_GTRC =  9
00084 N_GTFE = 24
00085 
00086 N_GARC = 12
00087 N_GAFE = 18
00088 
00089 GTCC_MAP     = [6, 3, 7, 2, 5, 0, 4, 1]
00090 GTCC_ERR_MAP = [3, 6, 2, 7, 0, 5, 1, 4]
00091 
00092 GCCC_MAP = [0, 2, 3, 1]
00093 
00094 # AEM class
00095 class AEM(object):
00096   """\brief AEM event object
00097 
00098   Members:
00099   - \c vetoHitVectors
00100   - \c acceptHitVectors
00101   - \c PHA
00102 
00103   """
00104   EV_AEM_VETO = 1
00105   EV_AEM_ZEROSUP = 2
00106 
00107   def __init__(self):
00108     self.clearEvent()
00109 
00110   def clearEvent(self):
00111     """\brief Initialize accept and veto hit vectors
00112 
00113     """
00114     self.vetoHitVectors = [0]*N_GARC
00115     self.acceptHitVectors = [0]*N_GARC
00116     self.PHA = {}
00117     for cbl in range(N_GARC):
00118       self.PHA[cbl] = []
00119 
00120   def addPHA(self, cbl, pha):
00121     """\brief Adds a PHA value.
00122 
00123     Called from evDumpAEM_PHA
00124 
00125     \param cbl Cable number
00126     \param pha 16 bit PHA value
00127     """
00128     self.PHA[cbl].append(pha)
00129 
00130 class evAEM_PHA(BitField):
00131   """\brief PHA object
00132 
00133   Bit Fields:
00134   - \c more
00135   - \c range
00136   - \c ADC
00137   - \c parityErr
00138 
00139   """
00140   evAEM_PHA_BF =  [
00141                     ('more',         14, 15),
00142                     ('range',        13, 14),
00143                     ('ADC',           1, 13),
00144                     ('parityErr',     0,  1)
00145                   ]
00146   def __init__(self, ui):
00147     BitField.__init__(self, ui, self.evAEM_PHA_BF)
00148 
00149 class GEM(object):
00150   """\brief GEM event object.
00151 
00152   Members:
00153   - \c ROI_Vector
00154   - \c TKR_Vector
00155   - \c CAL_HE_Vector
00156   - \c CAL_LE_Vector
00157   - \c deadzone
00158   - \c conditions
00159   - \c CNO_Vector
00160   - \c vetoList
00161   - \c liveTime
00162   - \c prescaled
00163   - \c discarded
00164   - \c condArrivalTimes
00165   - \c triggerTime
00166   - \c onePPSTime
00167   - \c deltaOpenWindowTime
00168   - \c deltaEventTime
00169 
00170   \deprecated
00171   - \c \b triggerSummary Use 'conditions' instead
00172   - \c \b sent           Use 'condArrivalTimes' instead
00173 
00174   """
00175   def __init__(self):
00176     self.vetoList = evGEM_Veto_List()
00177     self.condArrivalTimes = evGEM_Cond_Arrival_Times(0)
00178     self.clear()
00179 
00180   def clear(self):
00181     self.ROI_Vector = 0
00182     self.TKR_Vector = 0
00183     self.CAL_HE_Vector = 0
00184     self.CAL_LE_Vector = 0
00185     self.triggerSummary = 0 # Deprecated
00186     self.deadzone = 0
00187     self.conditions = 0
00188     self.CNO_Vector = 0
00189     self.vetoList.clear()
00190     self.liveTime = 0
00191     self.prescaled = 0
00192     self.discarded = 0
00193     self.sent = 0 # Deprecated
00194     self.condArrivalTimes.set(0)
00195     self.triggerTime = 0
00196     self.onePPSTime = 0
00197     self.deltaOpenWindowTime = 0
00198     self.deltaEventTime = 0
00199 
00200 class evGEM_Veto_List(object):
00201   """\brief GEM Veto List object.
00202 
00203   Members:
00204   - \c XZP
00205   - \c XZM
00206   - \c YZP
00207   - \c YZM
00208   - \c XY
00209   - \c NA
00210   - \c RBN
00211 
00212   """
00213   def __init__(self):
00214     self.clear()
00215 
00216   def clear(self):
00217     self.XZP = 0
00218     self.XZM = 0
00219     self.YZP = 0
00220     self.YZM = 0
00221     self.XY  = 0
00222     self.NA  = 0
00223     self.RBN = 0
00224 
00225 class evGEM_Cond_Arrival_Times(BitField):
00226   """\brief GEM Condition Arrival Times bitfield.
00227 
00228   Members:
00229   - \c External
00230   - \c CNO
00231   - \c CAL_HE
00232   - \c CAL_LE
00233   - \c TKR
00234   - \c ROI
00235 
00236   """
00237   evGEM_Cond_Arrival_Times_BF =  [
00238                     ('External',     25, 30),
00239                     ('CNO',          20, 25),
00240                     ('CAL_HE',       15, 20),
00241                     ('CAL_LE',       10, 15),
00242                     ('TKR',           5, 10),
00243                     ('ROI',           0,  5)
00244                   ]
00245   def __init__(self, ui):
00246     BitField.__init__(self, ui, self.evGEM_Cond_Arrival_Times_BF)
00247 
00248 
00249 class Evt(object):
00250   """\brief Event object
00251 
00252   Members:
00253   - \c aem
00254   - \c gem
00255   - \c contributor
00256   - \c summary
00257   - \c TKRstrips
00258   - \c TKRaccepts
00259   - \c TKRtots
00260   - \c CAL_LogAccepts
00261   - \c CAL_LogData
00262   - \c diag
00263   - \c errSummary
00264   - \c errGCCCmsg
00265   - \c errGTCCmsg
00266   - \c errCablePhase
00267   - \c errCableTimeOut
00268 
00269   """
00270   def __init__(self):
00271     """\brief Event object constructor.
00272 
00273     Instantiate the AEM object and clear the event.
00274     """
00275     self.aem = AEM()
00276 ## New Event Format
00277     self.gem = GEM()
00278 ##
00279     self.clearEvent()
00280 
00281   def clearEvent(self):
00282     """\brief Clear the event data
00283 
00284     """
00285     self.contributor = None
00286     self.summary = None
00287     self.TKRstrips = []
00288     self.TKRaccepts = []
00289     self.TKRtots = []
00290     self.CAL_LogAccepts = []
00291     self.CAL_LogData = []
00292     self.diag = None
00293     self.errSummary = None
00294     self.errGCCCmsg = []
00295     self.errGTCCmsg = []
00296     self.errCablePhase = None
00297     self.errCableTimeOut = None
00298 
00299   def addTKRstrip(self, cc, rc, strip):
00300     """\brief Add a stripData to the tracker strip hit list of evTKR_StripData objects.
00301 
00302     \param cc    Cable controller id
00303     \param rc    Readout controller id
00304     \param strip evTKR_Strip object instance
00305     """
00306     self.TKRstrips.append(evTKR_StripData(cc, rc, strip))
00307 
00308   def addTKRaccept(self, accept):
00309     """\brief Add a TKR accept to the list
00310 
00311     \param 9-bit TKR accept value
00312     """
00313     self.TKRaccepts.append(accept)
00314 
00315   def addTKRtot(self, cc, rc, tot):
00316     """\brief Add a TKR tot to the list of evTKR_TOTdata objects.
00317 
00318     \param cc    Cable controller id
00319     \param rc    Readout controller id
00320     \param tot   8-bit tot value
00321     """
00322     self.TKRtots.append(evTKR_TOTdata(cc, rc, tot))
00323 
00324   def addCAL_LogAccept(self, accept):
00325     """\brief Add a log accept to the list
00326 
00327     \param accept An evCAL_LogAccepts object instance
00328     """
00329     self.CAL_LogAccepts.append(accept)
00330 
00331   def addCAL_LogData(self, twr, layer, data):
00332     """\brief Add a log data to the list
00333 
00334     \param layer A layer id in the form of 'x1', 'y1', etc.
00335     \param data  An evCAL_LogData object instance
00336     """
00337     self.CAL_LogData.append(evCAL_LayerLogData(twr, layer, data))
00338 
00339   def addErrGCCCmsg(self, errGCCC):
00340     """\brief Add a GCCC error contribution to the event object
00341 
00342     \param errGCCC An evErr_GCCC object instance
00343     """
00344     self.errGCCCmsg.append(errGCCC)
00345 
00346   def addErrGTCCmsg(self, errGTCCmsg):
00347     """\brief Add a GTCC error message to the event object
00348 
00349     \param errGTCCmsg An evErr_GTCC_Message object instance
00350     """
00351     self.errGTCCmsg.append(errGTCCmsg)
00352 
00353 class evErr_Summary(BitField):
00354   """\brief Error summary bitfields
00355 
00356   Bit Fields:
00357   - \c cblTimeOut
00358   - \c cblPhsErr
00359   - \c gtccErr
00360   - \c gcccErr
00361 
00362   """
00363   evErr_Summary_BF =  [
00364                         ('cblTimeOut',  13, 14),
00365                         ('cblPhsErr',   12, 13),
00366                         ('gtccErr',      4, 12),
00367                         ('gcccErr',      0,  4)
00368                       ]
00369   def __init__(self, ui):
00370     BitField.__init__(self, ui, self.evErr_Summary_BF)
00371 
00372 class evSummary(BitField):
00373   """\brief Event summary bitfields
00374 
00375   Bit Fields:
00376   - \c startbit
00377   - \c calStrobe
00378   - \c tag
00379   - \c TACK
00380   - \c readout4
00381   - \c zeroSuppress
00382   - \c marker
00383   - \c error
00384   - \c diag
00385   - \c evNumber
00386   - \c trgParityErr
00387 
00388   """
00389   evSummary_BF =  [
00390                     ('startbit ',     31, 32),
00391                     ('calStrobe',     30, 31),
00392                     ('tag',           28, 30),
00393                     ('TACK',          27, 28),
00394                     ('readout4',      26, 27),
00395                     ('zeroSuppress',  25, 26),
00396                     ('marker',        22, 25),
00397                     ('error',         21, 22),
00398                     ('diag',          20, 21),
00399                     ('evNumber',       1, 16),
00400                     ('trgParityErr',   0,  1)
00401                   ]
00402   def __init__(self, ui):
00403     BitField.__init__(self, ui, self.evSummary_BF)
00404 
00405 class evSummary_Singleton(evSummary):
00406   def __init__(self, ui):
00407     evSummary.__init__(self, ui)
00408 
00409   def __call__(self, ui):
00410     self.set(ui)
00411     return self
00412 
00413 class evContPacket(BitField):
00414   """\brief Contribution Packet bitfields
00415 
00416   Bit Fields:
00417   - \c error
00418   - \c sequence
00419   - \c length
00420 
00421   """
00422   evContPacket_BF = [
00423                     ('error',     13, 16),
00424                     ('sequence',   8, 13),
00425                     ('length',     0,  8),
00426                   ]
00427   def __init__(self, ui):
00428     BitField.__init__(self, ui, self.evContPacket_BF)
00429 
00430 class evContPacket_Singleton(evContPacket):
00431   def __init__(self, ui):
00432     evContPacket.__init__(self, ui)
00433 
00434   def __call__(self, ui):
00435     self.set(ui)
00436     return self
00437 
00438 class evTKR_TOTdata(object):
00439   """\brief TKR TOT data class
00440 
00441   Members:
00442   - \c tot
00443   - \c cc
00444   - \c rc
00445 
00446   """
00447   def __init__(self, cc, rc, tot):
00448     """\brief evTKR_TOTdata constructor
00449 
00450     \param cc  Cable controller id
00451     \param rc  Readout controller id
00452     \param tot 8-bit TOT value
00453 
00454     """
00455     self.tot = tot
00456     self.cc = cc
00457     self.rc = rc
00458 
00459 class evTKR_Strip(BitField):
00460   """\brief TKR strip bitfields
00461 
00462   Bit Fields:
00463   - \c done
00464   - \c gtfe
00465   - \c strip
00466 
00467   """
00468   evTKR_Strip_BF =  [
00469                       ('done',    11, 12),
00470                       ('gtfe',     6, 11),
00471                       ('strip',    0,  6)
00472                     ]
00473   def __init__(self, ui):
00474     BitField.__init__(self, ui, self.evTKR_Strip_BF)
00475 
00476 class evTKR_StripData(object):
00477   """\brief TKR StripData class
00478 
00479   Members:
00480   - \c cc
00481   - \c rc
00482   - \c strip
00483 
00484   """
00485   def __init__(self, cc, rc, strip):
00486     """\brief evTKR_StripData constructor
00487 
00488     \param cc    Cable controller id
00489     \param rc    Readout controller id
00490     \param strip An evTKR_Strip object instance
00491     """
00492     self.strip = strip
00493     self.cc = cc
00494     self.rc = rc
00495 
00496 class evCAL_LogAccepts(BitField):
00497   """\brief Log Accepts bitfields
00498 
00499   Bit Fields:
00500   - \c y3
00501   - \c y2
00502   - \c y1
00503   - \c y0
00504   - \c x3
00505   - \c x2
00506   - \c x1
00507   - \c x0
00508 
00509   """
00510   evCAL_LogAccepts_BF = [
00511                           ('y3',    28, 32),
00512                           ('y2',    24, 28),
00513                           ('y1',    20, 24),
00514                           ('y0',    16, 20),
00515                           ('x3',    12, 16),
00516                           ('x2',     8, 12),
00517                           ('x1',     4,  8),
00518                           ('x0',     0,  4)
00519                         ]
00520   def __init__(self, twr, ui):
00521     BitField.__init__(self, ui, self.evCAL_LogAccepts_BF)
00522     self.twr = twr
00523 
00524 class evCAL_LayerLogData(object):
00525   """\brief Class that associates a layer with the log data
00526 
00527   """
00528   def __init__(self, twr, layer, data):
00529     """\brief evCAL_LayerLogData constructor
00530 
00531     \param layer CAL layer (such as 'x1', 'y1', etc)
00532     \param data  evCAL_LogData bitfield
00533     """
00534     self.twr   = twr
00535     self.layer = layer
00536     self.data  = data
00537 
00538 class evCAL_LogData(BitField):
00539   """\brief Log Data bitfields
00540 
00541   Bit Fields:
00542   - \c column
00543   - \c rangeADC_neg
00544   - \c valADC_neg
00545   - \c rangeADC_pos
00546   - \c valADC_pos
00547 
00548   """
00549   evCAL_LogData_BF =  [
00550                         ('column',       28, 32),
00551                         ('rangeADC_neg', 26, 28),
00552                         ('valADC_neg',   14, 26),
00553                         ('rangeADC_pos', 12, 14),
00554                         ('valADC_pos',    0, 12)
00555                       ]
00556   def __init__(self, ui):
00557     BitField.__init__(self, ui, self.evCAL_LogData_BF)
00558 
00559 class evDiag_CalLayerEnd(BitField):
00560   """\brief Calorimeter Layer End bitfields
00561 
00562   Bit Fields:
00563   - \c trgRequestHigh
00564   - \c trgRequestLow
00565   - \c logAccepts
00566 
00567   """
00568   evDiag_CalLayerEnd_BF =   [
00569                               ('trgRequestHigh',  13, 14),
00570                               ('trgRequestLow',   12, 13),
00571                               ('logAccepts',       0, 12)
00572                             ]
00573   def __init__(self, ui):
00574     BitField.__init__(self, ui, self.evDiag_CalLayerEnd_BF)
00575 
00576 class evDiag_CalLayer:
00577   """\brief Calorimeter Layer class
00578 
00579   Members:
00580   - \c gccc
00581   - \c layer
00582   - \c negLayerEnd
00583   - \c posLayerEnd
00584 
00585   """
00586   def __init__(self):
00587     self.gccc        = None
00588     self.layer       = None
00589     self.negLayerEnd = evDiag_CalLayerEnd(0)
00590     self.posLayerEnd = evDiag_CalLayerEnd(0)
00591 
00592 
00593 class evDiag_TkrTrgReq(BitField):
00594   """\brief TKR Trigger Request bitfields
00595 
00596   Members:
00597   - \c gtcc
00598 
00599   Bit Fields:
00600   - \c trgRequests
00601 
00602   """
00603   evDiag_TkrTrgReq_BF =   [
00604                             ('trgRequests',  0, 9)
00605                           ]
00606   def __init__(self, ui):
00607     BitField.__init__(self, ui, self.evDiag_TkrTrgReq_BF)
00608     self.gtcc = None
00609 
00610 class evErr_GCCC(BitField):
00611   """\brief GCCC Error bitfields
00612 
00613   Bit Fields:
00614 
00615   - \c errParm
00616   - \c sweepNum
00617   - \c errType
00618 
00619   """
00620   evErr_GCCC_BF =   [
00621                       ('errParm',   8, 16),
00622                       ('sweepNum',  6,  8),
00623                       ('errType',   0,  4)
00624                     ]
00625   def __init__(self, ui):
00626     BitField.__init__(self, ui, self.evErr_GCCC_BF)
00627 
00628 class evErr_GCCC_Message(object):
00629   """\brief GCCC Error Message object
00630 
00631   Members:
00632   - \c gccc
00633   - \c errGCCC
00634 
00635   """
00636   def __init__(self, gccc, errGCCC):
00637     """\brief evErr_GCCC_Message constructor
00638 
00639     \param gccc    GCCC id
00640     \param errGCCC evErr_GCCC object instance
00641     """
00642     self.gccc       = gccc
00643     self.errGCCC    = errGCCC
00644 
00645 class evErr_CablePhase(BitField):
00646   """\brief Cable Controller Phasing Error bitfields
00647 
00648   Bit Fields:
00649   - \c tag7
00650   - \c tag6
00651   - \c tag5
00652   - \c tag4
00653   - \c tag3
00654   - \c tag2
00655   - \c tag1
00656   - \c tag0
00657 
00658   """
00659   evErr_CablePhase_BF = [
00660                           ('tag7', 14, 16),
00661                           ('tag6', 12, 14),
00662                           ('tag5', 10, 12),
00663                           ('tag4',  8, 10),
00664                           ('tag3',  6,  8),
00665                           ('tag2',  4,  6),
00666                           ('tag1',  2,  4),
00667                           ('tag0',  0,  2)
00668                         ]
00669   def __init__(self, ui):
00670     BitField.__init__(self, ui, self.evErr_CablePhase_BF)
00671 
00672 class evErr_GTCC(BitField):
00673   """\brief GTCC Error bitfields
00674 
00675   Bit Fields:
00676   - \c dataParity
00677   - \c GTRCsum
00678   - \c wrdCntParity
00679   - \c hdrParity
00680   - \c cblTimeOut
00681   - \c fifoFull
00682   - \c phsGTFE
00683   - \c phsGTRC
00684   - \c nGTRC
00685 
00686   """
00687   evErr_GTCC_BF =   [
00688                       ('dataParity',    15, 16),
00689                       ('GTRCsum',       14, 15),
00690                       ('wrdCntParity',  13, 14),
00691                       ('hdrParity',     12, 13),
00692                       ('cblTimeOut',    11, 12),
00693                       ('fifoFull',      10, 11),
00694                       ('phsGTFE',        9, 10),
00695                       ('phsGTRC',        8,  9),
00696                       ('nGTRC',          0,  8)
00697                     ]
00698   def __init__(self, ui):
00699     BitField.__init__(self, ui, self.evErr_GTCC_BF)
00700 
00701 class evErr_GTCC_Message(object):
00702   """\brief GTCC Error Message object
00703 
00704   Members:
00705   - \c gtcc
00706   - \c errGTCC
00707   - \c parameters
00708 
00709   """
00710   def __init__(self):
00711     self.gtcc       = None
00712     self.errGTCC    = None
00713     self.parameters = {}
00714 
00715 
00716 class evErr_CableTimeOut(BitField):
00717   """\brief Cable Timeout Error bitfields
00718 
00719   Bit Fields:
00720   - \c tkr
00721   - \c cal
00722 
00723   """
00724   evErr_CableTimeOut_BF = [
00725                             ('tkr',  4, 12),
00726                             ('cal',  0,  4)
00727                           ]
00728   def __init__(self, ui):
00729     BitField.__init__(self, ui, self.evErr_CableTimeOut_BF)
00730 
00731 
00732 class evDiag_Data(object):
00733   """\brief Diagnostic Data class
00734 
00735   Members:
00736   - \c cal
00737   - \c tkr
00738 
00739   """
00740   size = 48 # 8*(4 + 2)
00741   def __init__(self):
00742     self.cal = []
00743     self.tkr = []
00744     for i in range(8):
00745       inst = evDiag_CalLayer()
00746       self.cal.append(inst)
00747       inst = evDiag_TkrTrgReq(0)
00748       self.tkr.append(inst)
00749 
00750 class evCellHeader(BitField):
00751   """\brief Cell Header bitfields
00752 
00753   Bit Fields:
00754   - \c respond
00755   - \c destination
00756   - \c protocol
00757   - \c source
00758   - \c parity
00759 
00760   """
00761   evCellHeader_BF = [
00762                       ('respond',    15, 16),
00763                       ('destination', 9, 15),
00764                       ('protocol',    7,  9),
00765                       ('source',      1,  7),
00766                       ('parity',      0,  1),
00767                     ]
00768   def __init__(self, ui):
00769     BitField.__init__(self, ui, self.evCellHeader_BF)
00770 
00771 class evCellHeader_Singleton(evCellHeader):
00772   def __init__(self, ui):
00773     evCellHeader.__init__(self, ui)
00774 
00775   def __call__(self, ui):
00776     self.set(ui)
00777     return self
00778 
00779 
00780 class EvtCliIO(Socket):
00781   """\brief Event client input/output class
00782 
00783 \b Contents:
00784 
00785   This base class contains all the input/output handling routines for the event client (EvtCli) class.
00786 
00787   """
00788 
00789   EVENT_SRC_SOCK = 0
00790   EVENT_SRC_FILE = 1
00791   PortNumber = 2000
00792 
00793   def __init__(self, debug, port=PortNumber):
00794     Socket.__init__(self, port)
00795     self.read                = None
00796     self.__abort             = 0
00797     self.__timeout           = 1        # !!!!
00798     self.__timeoutEnabled    = 0
00799     self.__debugErrorOutput  = debug & (EvtCli.DEBUG_ALL | EvtCli.DEBUG_ERROR_OUTPUT)
00800 
00801   def connect(self, host, force=False):
00802     Socket.connect(self, host)
00803     self.read = self.readSocket
00804     if force: opcode = Opcode(Opcode.ForceEventSocket)
00805     else:     opcode = Opcode(Opcode.SetEventSocket)
00806     self.send(opcode.packet())
00807     dat = self.recvall(8)
00808     [size, status] = struct.unpack('!2L', dat)
00809     if status & 0x3: raise LATInterfaceException(status)
00810 
00811   def setSocket(self, sock):
00812     Socket.setSocket(self, sock)
00813     self.read = self.readSocket
00814 
00815   def readSocket(self):
00816     """\brief The 'lightweight' event read routine.
00817 
00818     This routine does the minimal work of reading the raw
00819     event data from a file or a socket.
00820 
00821     \return Event buffer read
00822     """
00823     self.__abort = 0
00824     while not self.__abort:
00825       rd, wr, ex = select.select([self.socket()], [], [], self.__timeout)
00826       if rd:
00827         dat = self.recvall(28)
00828         header = struct.unpack('!7L', dat)
00829         numLeft = header[2] - 24
00830         dat += self.recvall(numLeft)
00831         return (header, dat[4:])
00832       elif self.__timeoutEnabled:
00833         raise IOError, "Event read timeout"
00834     # Abort:
00835     raise RuntimeError, "EvtCli.readSocket was aborted"
00836 
00837   def readFile(self):
00838     """\brief Read the event from a file.
00839 
00840     """
00841     # The archive file includes the first two datagram words
00842     dat = self.__f.read(20)
00843     header = (0,)
00844     header += struct.unpack('!5L', dat)
00845     numLeft = (header[2] & 0xFFFF) - 20
00846     dat += self.__f.read(numLeft)
00847     return (header, dat)
00848 
00849   def open(self,filename,mode="r+b"):
00850     """\brief Open the event archive file for input.
00851 
00852     \param filename Event archive file name
00853     """
00854     self.__f=file(filename, mode)
00855     self.read = self.readFile
00856 
00857   def close(self):
00858     """\brief Close the event source file.
00859     """
00860     self.__f.close()
00861 
00862   def abort(self):
00863     """\brief Abort out of a readEvent().
00864 
00865     Can be used from another thread
00866     """
00867     self.__abort = 1
00868 
00869   def setTimeoutEnabled(self, flag):
00870     """\brief Enable or disable event timeout
00871 
00872     \param flag 1 = Enable event timeout
00873                 0 = Disable event timeout (default)
00874     """
00875     self.__timeoutEnabled = flag;
00876 
00877   def isTimeoutEnabled(self):
00878     """\brief Checks the event timeout state
00879 
00880     \return 1 = If event timeout is enabled
00881             0 = If event timeout is disabled
00882     """
00883     return self.__timeoutEnabled
00884 
00885   def setTimeout(self, timeout = 1.0):
00886     """\brief Set the timeout value.
00887 
00888     \param timeout Event timeout value as a floating point number in seconds.
00889                    Default is 1 second.  Use 'None' to disable the timeout.
00890     """
00891     #self.__timeout = timeout
00892     self.socket().settimeout(timeout)
00893 
00894   def getTimeout(self):
00895     """\brief Query the current timeout value.
00896 
00897     \return Current event timeout value as a floating point number in seconds
00898     """
00899     #return self.__timeout
00900     return self.socket().gettimeout()
00901 
00902   def unpack(self, fmt, str):
00903     """\brief Wrapper method for unpack
00904 
00905     \param  fmt Unpack format
00906     \param  str String to be unpacked
00907 
00908     \return     Unpacked data tuple
00909     """
00910     try:
00911       result = struct.unpack(fmt, str)
00912     except:
00913       if self.__debugErrorOutput:
00914         logException()
00915         logStack()
00916       return ()
00917     else:
00918       return result
00919 
00920 
00921 class EvtCli(EvtCliIO):
00922   """\brief Event handler client
00923 
00924 \b Contents:
00925 
00926   Receives an event from TCP socket or a file stream and
00927   parses it into the evt object.
00928 
00929 \b Overview:
00930 
00931   The event client is responsible for communicating with the event server
00932   and retrieve events triggered by a script or an external source.
00933   The source of the event can be either a TCP socket or an archive file.
00934 
00935   The event client uses lazy parsing to parse the event. This means the
00936   user application needs to call the parsing routines that corresponds
00937   to the section of the event that the user is interested in. The parser
00938   methods populate event objects inside the Evt class in the event client,
00939   so after the parser method is called these objects can be accessed or
00940   iterated over. The parser methods only apply to the current contribution.
00941   By default after readEvent() the first contribution after the GEM
00942   contribution is the current contribution. Use the setCurrentContribution
00943   method to change the current contribution. Use the getContributionList
00944   method to find out which contributions exist in the event.
00945 
00946   Available parser methods:
00947     - evDumpSummary()
00948     - evDumpCAL_LogAccepts()
00949     - evDumpCAL_Logs()
00950     - evDumpTKR()
00951     - evDumpDiagnostic()
00952     - evDumpTEM_Error()
00953     - evDumpEventAEM()
00954 
00955   Contribution related methods:
00956   - getContributionList()
00957   - getCurrentContribution()
00958   - setCurrentContribution()
00959   - dumpContributionData()
00960 
00961   Retrieving the timestamp and timebase:
00962   - evGetTimestamp()
00963   - evGetTimebase()
00964 
00965 \b Usage:
00966 
00967   For reading events from a socket:
00968   \code
00969     from gEvtCli import *
00970     ec = EvtCli(debug=0)
00971     ec.connect('gitot')
00972     while ec.readEvent() == 0:
00973       ec.setCurrentContribution(...)
00974       if ec.getContributionStatus() == 0:
00975         ec.evDumpXXX()
00976         :
00977       else:
00978         print "Error %s in contribution %s ",
00979           (ec.getContributionStatusStr(), cId)
00980     ec.disconnect()
00981   \endcode
00982   For reading events from an archived event file:
00983   \code
00984     from gEvtCli import *
00985     ec = EvtCli(debug=0)
00986     ec.open('030305165528.ldf')
00987     while ec.readEvent() == 0:
00988       ec.setCurrentContribution(...)
00989       if ec.getContributionStatus() == 0:
00990         ec.evDumpXXX()
00991         :
00992       else:
00993         print "Error %s in contribution %s ",
00994           (ec.getContributionStatusStr(), cId)
00995     ec.close()
00996   \endcode
00997   For looping over contributions:
00998   \code
00999     from gEvtCli import *
01000     ec = EvtCli(debug=0)
01001     ec.connect('gitot')
01002     status = ec.readEvent()
01003     contList = ec.getContributionList()
01004     for cId in contList:
01005       ec.setCurrentContribution(cId)
01006       if ec.getContributionStatus() == 0:
01007         ec.evDumpSummary()
01008         if cId.startswith('TEM'):
01009           ec.evDumpCAL_LogAccepts()
01010           ec.evDumpCAL_Logs()
01011           ec.evDumpTKR()
01012           ec.evDumpTEM_Error()
01013           ec.evDumpDiagnostic()
01014         elif cId == 'AEM':
01015           ec.evDumpEventAEM()
01016       else:
01017         print "Error %s in contribution %s ",
01018           (ec.getContributionStatusStr(), cId)
01019   \endcode
01020   """
01021 
01022   __SWEEP_MARKER = 5            # Arbitrary marker value for recognizing
01023                                 #   when the event pipeline is flushed
01024   EVENT_SRC_SOCK = 0
01025   EVENT_SRC_FILE = 1
01026   DATAGRAM_IDENTITY = 0x201F1010
01027   UNRECOGNIZED_BUFFER_IDENTITY = 0x201F1020
01028   MINIMAL_BYTES = 32
01029   FIRST_CONTRIBUTION_OFFSET = 4 # In 32-bit words
01030 ## New event format
01031 ##  EXPECTED_EVENT_VERSION = 0x101F0010
01032 ##  EXPECTED_EVENT_VERSION = 0x102F0010
01033 ##  EXPECTED_EVENT_VERSION = 0x103F0010
01034   EXPECTED_EVENT_VERSION = 0x104F0010
01035 ##
01036 
01037   # Errors that the getOnlineStatus() method can return
01038   ERROR_BASE             = 0x1000
01039   GGLT_STATUS_ERROR      = ERROR_BASE + (1 << 0)
01040   MINIMAL_SIZE_ERROR     = ERROR_BASE + (1 << 1)
01041   EOE_ERROR              = ERROR_BASE + (1 << 2)
01042   UNPACK_ERROR           = ERROR_BASE + (1 << 3)
01043   IO_ERROR               = ERROR_BASE + (1 << 4)
01044   EVENT_VERSION_MISMATCH = ERROR_BASE + (1 << 5)
01045   PLAYBACK_ERROR         = ERROR_BASE + (1 << 6) # Agrees with evtSvr.c
01046   READ_TIMEOUT_ERROR     = ERROR_BASE + (1 << 7)
01047   EOF_ERROR              = ERROR_BASE + (1 << 8)
01048   ABORT_ERROR            = ERROR_BASE + (1 << 9)
01049 
01050   # Errors that the getContributionStatus() method can return
01051   CONTRIB_ERR_NONE        = 0
01052   CONTRIB_ERR_PARITY      = 1
01053   CONTRIB_ERR_TRUNCATED   = 2
01054   CONTRIB_ERR_WRITE_FAULT = 3
01055   CONTRIB_ERR_TIMEDOUT    = 4
01056 
01057   CONTRIBUTOR = {  0:'TEM0',
01058                    1:'TEM1',
01059                    2:'TEM2',
01060                    3:'TEM3',
01061                    4:'TEM4',
01062                    5:'TEM5',
01063                    6:'TEM6',
01064                    7:'TEM7',
01065                    8:'TEM8',
01066                    9:'TEM9',
01067                   10:'TEM10',
01068                   11:'TEM11',
01069                   12:'TEM12',
01070                   13:'TEM13',
01071                   14:'TEM14',
01072                   15:'TEM15',
01073                   16:'GEM',
01074                   17:'AEM',
01075                   32:'OSW'
01076                 }
01077 
01078   (
01079     TEM0,
01080     TEM1,
01081     TEM2,
01082     TEM3,
01083     TEM4,
01084     TEM5,
01085     TEM6,
01086     TEM7,
01087     TEM8,
01088     TEM9,
01089     TEM10,
01090     TEM11,
01091     TEM12,
01092     TEM13,
01093     TEM14,
01094     TEM15,
01095     GEM,
01096     AEM,
01097     _NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,_NA,
01098     OSW,
01099   ) = \
01100   ( range (0,33) )
01101 
01102   # Debug levels
01103   DEBUG_NONE          = 0
01104   DEBUG_ALL           = 1
01105   DEBUG_EVENT_DUMP    = 1 << 1
01106   DEBUG_WARNINGS      = 1 << 2
01107   DEBUG_PARSER_OUTPUT = 1 << 3
01108   DEBUG_ERROR_OUTPUT  = 1 << 4
01109 
01110   def __init__(self, debug=0, port=EvtCliIO.PortNumber):
01111     """\brief Event client constructor
01112 
01113     \param debug  Debug mode (0=Debug, 1=No debug)
01114     """
01115 
01116     if debug is None:
01117       self.setDebug(0)
01118     else:
01119       self.setDebug(int(debug))
01120 
01121     EvtCliIO.__init__(self, self.__debug, port)
01122 
01123     self.__sock              = None
01124     self.__src               = None
01125     self.evt                 = Evt()
01126     self.__evContPacket      = evContPacket_Singleton(0)
01127     self.__evSummary         = evSummary_Singleton(0)
01128     self.__evCellHeader      = evCellHeader_Singleton(0)
01129     self.__oes_status        = 0
01130     self.__online_status     = 0
01131     self.__evt_status        = None
01132     self.__evt_size          = None
01133     self.__version_info      = None
01134     self.latInterfaceStatus  = LATInterfaceStatus(0)
01135 
01136     # Make sure the custom event client does not override EvtCliIO.read() method
01137     customEvtCli = EvtCli.__subclasses__()
01138     if len(customEvtCli) != 0:
01139       customEvtCli = customEvtCli[0]
01140       if 'read' in customEvtCli.__dict__:
01141         raise RuntimeError, "Custom event client %s should not override the read() method" % customEvtCli.__name__
01142 
01143   def setDebug(self, debug):
01144     """\brief Set the debug mode
01145 
01146     \param debug Debug mode
01147                  The following debug modes are available and can be added together
01148                  for combinations:
01149                      0: No Debug
01150                      1: Debug All
01151                      2: Event Dump
01152                      4: Warnings
01153                      8: Parser Output
01154                     16: Error Output
01155     """
01156     self.__debug             = debug
01157     self.__debugWarnings     = debug & (EvtCli.DEBUG_ALL | EvtCli.DEBUG_WARNINGS)
01158     self.__debugEventDump    = debug & (EvtCli.DEBUG_ALL | EvtCli.DEBUG_EVENT_DUMP)
01159     self.__debugErrorOutput  = debug & (EvtCli.DEBUG_ALL | EvtCli.DEBUG_ERROR_OUTPUT)
01160     self.__debugParserOutput = debug & (EvtCli.DEBUG_ALL | EvtCli.DEBUG_PARSER_OUTPUT)
01161 
01162 
01163   def readEvent(self, dat=None):
01164     """\brief Read an event
01165 
01166     Reads one event from an archive file or socket
01167 
01168     \param  dat If not None then interpret this data as event instead
01169 
01170     \return     oes_status
01171     """
01172     evt = self.evt
01173     evt.clearEvent()
01174     evt.cont_offset = EvtCli.FIRST_CONTRIBUTION_OFFSET
01175     self.__online_status = 0
01176 
01177     if dat is not None:
01178       header = (0,)
01179       header += struct.unpack('!5L', dat[0:20])
01180       self.dat = dat
01181     else:
01182       (header, self.dat) = self.read()
01183       if header is None:
01184         return EvtCli.ABORT_ERROR
01185 
01186     self.header = header
01187 
01188     self.__oes_status   = header[0]
01189     self.__version_info = header[3]
01190     self.__evt_status   = header[4] >> 16
01191     self.__evt_size     = header[4] & 0xFFFF
01192 
01193     if self.__debugEventDump:
01194       print "OES status    = 0x%08x" % self.__oes_status
01195       print "Event version = 0x%08x" % self.__version_info
01196       dump_cells(self.dat)
01197     if self.__oes_status != 0:
01198       raise LATInterfaceException(self.__oes_status)
01199     if len(self.dat) < EvtCli.MINIMAL_BYTES:
01200       self.__online_status |= EvtCli.MINIMAL_SIZE_ERROR
01201       if self.__debugWarnings:
01202         log.error("*** gEvtCli: datagram size %d less than minimal bytes %d"
01203                   %(len(self.dat), EvtCli.MINIMAL_BYTES))
01204 
01205     if self.__version_info != EvtCli.EXPECTED_EVENT_VERSION:
01206       self.__online_status |= EvtCli.EVENT_VERSION_MISMATCH
01207       if self.__debugWarnings:
01208         log.error("*** gEvtCli: event version 0x%08x is not the expected 0x%08x"
01209                   %(self.__version_info, EvtCli.EXPECTED_EVENT_VERSION))
01210 
01211     if self.__online_status != 0:
01212       return self.__online_status
01213 
01214     # Get the summary word stored in the OSW contribution
01215     # to determine if the event has error.
01216     evt.summary = self.__evSummary(self.getDWord(self.evGetSummary()))
01217 
01218     if self.__debugEventDump:
01219       print "\nEvent Size            =", self.__evt_size
01220       print "Event Status          =", self.__evt_status
01221       ts = self.evGetTimestamp()
01222       print "Event Timestamp (GMT) =", asctime(gmtime(ts)), \
01223                                       "and", int(modf(ts)[0]*1000), "ms"
01224       print "Event timebase        =", hex(self.evGetTimebase())
01225       print "Event Sequence MSW    =", hex(self.evGetEvtSeqMSW())
01226       print "Event Sequence        =", hex(self.evGetEvtSequence())
01227 
01228     self.__evt_error = self.evt.summary.error
01229     self.__evt_trgParityError = self.evt.summary.trgParityErr
01230     # Get the OSW container packet
01231     osw_packet = self.__evContPacket(self.getDWord(evt.cont_offset) & 0xFFFF)
01232     self.__evt_packetError = osw_packet.error
01233 
01234     # Contribution offset (skip over the OSW contribution)
01235     evt.cont_offset += ((header[5] & 0xFFFF) << 2)
01236     cont_header = self.getDWord(evt.cont_offset)
01237     evt.cont_packet = self.__evContPacket(cont_header & 0xFFFF)
01238     evt.cont_status = evt.cont_packet.error
01239     evt.summary = self.__evSummary(self.getDWord(self.evGetSummary()))
01240     evt.cont_cellHeader = self.__evCellHeader(cont_header >> 16)
01241     evt.contributor = evt.cont_cellHeader.source
01242     evt.cont_size   = (cont_header & 0x00FF) << 4
01243     evt.cont_end    = (evt.cont_offset << 2) + evt.cont_size
01244 
01245     if self.__debugEventDump:
01246       print
01247       self.dumpContributionData()
01248 
01249     return self.__online_status
01250 
01251   def getGGLTStatus(self):
01252     """\brief Retrieve the GGLT status.
01253 
01254     If this status value is non zero then the event is considered "bad"
01255     """
01256     return self.__oes_status
01257 
01258   def getGGLTStatusStr(self):
01259     """\brief Return the string equivalent of the GGLT status code.
01260 
01261     """
01262     return self.latInterfaceStatus.errstr(self.__oes_status)
01263 
01264   def getOnlineStatus(self):
01265     """\brief Retrieve the Online status code.
01266 
01267     See getOnlineStatusStr method for a list of possible errors
01268 
01269     """
01270     return self.__online_status
01271 
01272   def getEvtStatus(self):
01273     """\brief Return the event status from the event header.
01274 
01275     """
01276     return self.__evt_status
01277 
01278   def getContributionStatus(self):
01279     """\brief Return the contribution status
01280 
01281     \return Contribution status
01282     """
01283     return self.evt.cont_status
01284 
01285   def getContributionStatusStr(self):
01286     """\brief Return the contribution status string
01287 
01288     \return Contribution status string
01289     """
01290     statusList = {0: 'NONE',
01291                   1: 'PARITY',
01292                   2: 'TRUNCATED',
01293                   3: 'WRITE_FAULT',
01294                   4: 'TIMEDOUT',
01295                  }
01296     if self.evt.cont_status in statusList:
01297       return statusList[self.evt.cont_status]
01298     else:
01299       return 'UNKNOWN ERROR'
01300 
01301   def getOnlineStatusStr(self):
01302     """\brief Retrieve the string equivalent of the Online status code.
01303 
01304     The error can be one of the following:
01305 
01306     GGLT_STATUS_ERROR     : A bad event was received. Call getGGLTStatusStr method
01307                             for the description.
01308     MINIMAL_SIZE_ERROR    : The event size was below the acceptable size.
01309     EOE_ERROR             : End of event was reached before the parse completed.
01310     UNPACK_ERROR          : There was an error while unpacking part of the event for parsing.
01311     IO_ERROR              : An I/O error occurred while retrieving the event (socket or file).
01312     EVENT_VERSION_MISMATCH: An event with an old or unsupported format was received.
01313     PLAYBACK_ERROR        : End of file was received while playing back an event archive file.
01314     READ_TIMEOUT_ERROR    : A read timeout occurred while waiting for the event to be
01315                             retrieved (Set by rcTransitions).
01316     EOF_ERROR             : End of file is reached while reading the event file.
01317 
01318     \return Online status string
01319 
01320     """
01321     statusList = ['GGLT_STATUS_ERROR',
01322                   'MINIMAL_SIZE_ERROR',
01323                   'EOE_ERROR',
01324                   'UNPACK_ERROR',
01325                   'IO_ERROR',
01326                   'EVENT_VERSION_MISMATCH',
01327                   'PLAYBACK_ERROR',
01328                   'READ_TIMEOUT_ERROR',
01329                   'EOF_ERROR',
01330                  ]
01331     s = ''
01332     status = self.__online_status & 0xFFF
01333     bitIndex = 0
01334     while (bitIndex < 12):
01335       if (1 << bitIndex) & status:
01336         if bitIndex < len(statusList):
01337           s += statusList[bitIndex] + ' '
01338         else:
01339           s += 'UNKNOWN_ERROR '
01340       bitIndex += 1
01341     return s.strip()
01342 
01343   def getEvtSize(self):
01344     """\brief Return the event size
01345 
01346     \return Event size
01347     """
01348     return self.__evt_size
01349 
01350   def isErrorEvent(self):
01351     """Determines whether at least one contribution
01352     has the error bit set in its summary word.
01353 
01354     \return 1: If at least one contribution has an error.
01355             0: Otherwise
01356     """
01357     return self.__evt_error
01358 
01359   def isTrgParityErrorEvent(self):
01360     """Determines whether at least one contribution
01361     has the trigger parity error bit set in its summary word.
01362 
01363     \return 1: If at least one contribution has an error.
01364             0: Otherwise
01365     """
01366     return self.__evt_trgParityError
01367 
01368   def isPacketErrorEvent(self):
01369     """Determines whether at least one contribution
01370     has a non-zero packet error set in the EBF contribution.
01371 
01372     \return 1: If at least one contribution has an error.
01373             0: Otherwise
01374     """
01375     return self.__evt_packetError != 0
01376 
01377   def isSweepEvent(self):
01378     """\brief Determine if a sweep event is received.
01379 
01380     User script can call this method in process() to determine if
01381     the current event is a sweep event. A try block around the call
01382     should be used in case a bad event is received.
01383 
01384     \return 0: Not a sweep event.
01385             1: A sweep event.
01386     """
01387     if self.evt.summary.marker == EvtCli.__SWEEP_MARKER:
01388       return 1
01389     else:
01390       return 0
01391 
01392   def isGGLTStatus(self, status=None):
01393     """\brief Determine if the current event is bad.
01394 
01395     User script can call this method in process() to determine if
01396     the current event is a bad event (gglt_status != 0).
01397 
01398     \param  Optional status value
01399 
01400     \return 0: Not a bad event.
01401             1: A bad event.
01402     """
01403     if status is None: status = self.__online_status
01404     return self.checkOnlineStatus(status, EvtCli.GGLT_STATUS_ERROR)
01405 
01406   def checkOnlineStatus(self, status, mask):
01407     """\brief Checks if the bit mask \a mask matches the \a status that is
01408     assumed as an Online status.
01409 
01410     \param status The status word to be checked against
01411     \param mask   The mask bit(s) to be checked
01412 
01413     \return 1 if there is a match
01414             0 if there is no match
01415 
01416     """
01417     if status < 0:
01418       return 0
01419     elif not (status & 0x1000):
01420       return 0
01421     else:
01422       return status & mask & 0xFFF
01423 
01424   def checkGGLTstatus(self, status, mask):
01425     """\brief Checks if the bit mask \a mask matches the \a status
01426     that is assumed as a GGLT status.
01427 
01428     \param status The status word to be checked against
01429     \param mask   The mask bit(s) to be checked
01430 
01431     \return 1 if there is a match
01432             0 if there is no match
01433 
01434     """
01435     if status > 0:
01436       return 0
01437     elif status & 0x1000:
01438       return 0
01439     else:
01440       return status & mask
01441 
01442   # The following function is experimental code: Do Not Use.
01443   def readEventSocket(self):
01444     # Maybe better to do this with setsockopt(SO_RCVLOWAT, 12) and select()
01445     l   = 0
01446     buf = ""
01447     while l < 12:
01448       buf += self.recv(4096 - l)
01449       l    = len(buf)
01450     (retCode, version, status, length) = self.unpack('!lLhH', buf[0:12])
01451     i = 0
01452     #print "readEventSocket:           %u, length = %u, l = %u" % (i, length, l)
01453     while l < length:
01454       buf += self.recv(4096 - l)
01455       l    = len(buf)
01456       i   += 1
01457       print "readEventSocket: Got more: %u, length = %u, l = %u" % (i, length,l)
01458     return (retCode, buf, l)
01459 
01460   def setCurrentContribution(self, contributionId):
01461     """\brief Given a contribution id, set the current contribution data
01462     needed for the parsing routines.
01463 
01464     \param  contributionId Integer contribution id
01465 
01466     \return The offset to the contribution requested.
01467             -1 If the contribution requested is not found
01468                or contribution offset was found to be larger
01469                than the event size
01470             Note: Use getContributionStatus() method after
01471                calling this routine to find out if the
01472                contribution has an error.
01473 
01474     """
01475     cont_offset = EvtCli.FIRST_CONTRIBUTION_OFFSET
01476     if isNumberType(contributionId):
01477       cId = contributionId
01478     else:
01479       for (key, value) in EvtCli.CONTRIBUTOR.items():
01480         if value == contributionId:
01481           cId = key
01482           break
01483     evt = self.evt
01484     while(True):
01485       cont_header = self.getDWord(cont_offset)
01486       evt.cont_packet = self.__evContPacket(cont_header & 0xFFFF)
01487       contributor = (cont_header >> 17) & 0x3F
01488       cont_size = evt.cont_packet.length << 4
01489       cont_cellHeader = self.__evCellHeader(cont_header >> 16)
01490       if contributor == cId:
01491         evt.cont_status = evt.cont_packet.error
01492         # Make sure it is a good contribution
01493         if evt.cont_status == 0:
01494           evt.cont_cellHeader = cont_cellHeader
01495           evt.contributor = contributor
01496           evt.cont_size = cont_size
01497           evt.cont_offset = cont_offset
01498           evt.cont_end = (cont_offset << 2) + cont_size
01499           evt.summary = self.__evSummary(self.getDWord(self.evGetSummary()))
01500           if self.__debugEventDump:
01501             self.dumpContributionData()
01502           return self.evt.cont_offset
01503       cont_offset += (cont_size >> 2)
01504       if cont_cellHeader.respond == 0:
01505         return -1
01506       if not (self.__evt_size > (cont_offset << 2)):
01507         return -1
01508 
01509   def getCurrentContribution(self):
01510     """\brief Return the integer id of the current contribution
01511 
01512     \return Current constribution id
01513     """
01514     return self.evt.cont_cellHeader.source
01515 
01516   def getContributionList(self):
01517     """\brief Walk through the whole event and construct a list of contribution id strings
01518 
01519     \return A list of contributors that have contributed to the current event
01520     """
01521     cont_offset = EvtCli.FIRST_CONTRIBUTION_OFFSET
01522     contributorList = []
01523     evt = self.evt
01524     while(True):
01525       cont_header = self.getDWord(cont_offset)
01526       cont_size = (cont_header & 0x00FF) << 4
01527       evt.cont_cellHeader = self.__evCellHeader(self.getDWord(cont_offset) >> 16)
01528       #if cont_size == 0:
01529       #  return contributorList
01530       contributor = (cont_header >> 17) & 0x3F
01531       contributorList = contributorList + [EvtCli.CONTRIBUTOR[contributor]]
01532       cont_offset += (cont_size >> 2)
01533       if evt.cont_cellHeader.respond == 0:
01534         return contributorList
01535       if not (self.__evt_size > (cont_offset << 2)):
01536         return contributorList
01537 
01538   def dumpContributionData(self):
01539     """\brief Prints out information pertaining to the current contribution.
01540 
01541     """
01542     if self.getContributionStatus() != 0:
01543       print("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***")
01544       print("   ***    This contribution is suspect. Error: %-15s ***"
01545             % self.getContributionStatusStr())
01546       print("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n")
01547 
01548     self.evDumpSummary(16)
01549     print
01550     print "Event Contributor=", EvtCli.CONTRIBUTOR[self.evt.contributor]
01551     print "Contribution size=", self.evt.cont_size
01552     print "\nPacket     = 0x%04X" % int(self.evt.cont_packet)
01553     print "\terror      =", hex(int(self.evt.cont_packet.error))
01554     print "\tsequence   =", hex(int(self.evt.cont_packet.sequence))
01555     print "\tlength     =", hex(int(self.evt.cont_packet.length))
01556     print "\nCell header= 0x%04X" % int(self.evt.cont_cellHeader)
01557     print "\tparity     =", hex(int(self.evt.cont_cellHeader.parity))
01558     print "\tsource     =", hex(int(self.evt.cont_cellHeader.source))
01559     print "\tprotocol   =", hex(int(self.evt.cont_cellHeader.protocol))
01560     print "\tdestination=", hex(int(self.evt.cont_cellHeader.destination))
01561     print "\trespond    =", hex(int(self.evt.cont_cellHeader.respond))
01562     dump_cells(self.dat[(self.evt.cont_offset<<2):self.evt.cont_end])
01563     print
01564 
01565   def evGetTimestamp(self):
01566     """\brief Return the timestamp of the event in seconds.
01567 
01568     The resolution of this timestamp is 1/60th of a second, by default.
01569     Consult VxWorks documentation for sysClkRateSet() and clock_setres()
01570     to see how to change this default. Beware that increasing the resolution
01571     from the default may cause adverse effects due to the increased
01572     interrupt rate generated.
01573 
01574     \return Timestamp of the event in seconds.
01575     """
01576 ## New Event Format
01577 ##    tv_sec  = self.getDWord(EvtCli.FIRST_CONTRIBUTION_OFFSET+2)
01578 ##    tv_nsec = self.getDWord(EvtCli.FIRST_CONTRIBUTION_OFFSET+3)
01579     tv_sec  = self.getDWord(EvtCli.FIRST_CONTRIBUTION_OFFSET+3)
01580     tv_nsec = self.getDWord(EvtCli.FIRST_CONTRIBUTION_OFFSET+4)
01581 ##
01582     return (tv_sec + (tv_nsec / 1000000000.0))
01583 
01584   def evGetTimebase(self):
01585     """\brief Return the timestamp of the event derived from the PPC timebase register.
01586 
01587     This is a 64 bit value that increments at an SBC implementation dependant
01588     rate (60 nS on MVME2306s).  The value is reset at PPC reset time.
01589 
01590     \return Timestamp of the event in PPC timebase ticks.
01591     """
01592     return self.unpack('!Q',
01593 ## New event format
01594 ##                       self.dat[(EvtCli.FIRST_CONTRIBUTION_OFFSET+4) << 2:
01595 ##                                (EvtCli.FIRST_CONTRIBUTION_OFFSET+6) << 2])[0]
01596                        self.dat[(EvtCli.FIRST_CONTRIBUTION_OFFSET+5) << 2:
01597                                 (EvtCli.FIRST_CONTRIBUTION_OFFSET+7) << 2])[0]
01598 ##
01599 
01600   # Not used anymore -ST
01601   #def extend(self, buffer):
01602   #  if self.dat is not None:
01603   #    self.dat += buffer
01604 
01605   def evGetEvtSeqMSW(self):
01606     """\brief Return the MSW portion of the event sequence
01607 
01608     \return MSW portion of the event sequence.
01609     """
01610     return self.getDWord(EvtCli.FIRST_CONTRIBUTION_OFFSET+7)
01611 
01612   def evGetEvtSequence(self):
01613     """\brief Return the Event Sequence
01614 
01615     \return Event sequence.
01616     """
01617     return ((self.evGetEvtSeqMSW()     << 17) |
01618             (self.evt.summary.evNumber <<  2) |
01619             (self.evt.summary.tag      <<  0)
01620           )
01621 
01622   def getUserId(self):
01623     """\brief Return the user id passed to the event client.
01624 
01625     \return Current user id
01626     """
01627     return 123 # Deprecated.
01628 
01629   def evGetTKR_Accepts(self, pAccept):
01630     """\brief Walks tower event contribution to the TKR accepts data.
01631 
01632     Fills in the evGetTKR_Accepts structure pointed to by \a pAccept
01633     with the TKR accepts data.  Also returns a pointer to the TKR
01634     accepts information.
01635 
01636     \param   pAccept Array to be filled with TKR accepts data
01637     \return  Offset to the start of TKR accepts data
01638 
01639     """
01640     p = self.evGetCAL_LogAccepts() + 1 + self.evGetCAL_NumAccepts() * (1 + 3 * self.evt.summary.readout4)
01641     if pAccept != None:
01642       for i in range(N_GTCC):
01643         dWordOffset = int(p + (9 * i) / 32)
01644         bitOffset  = (9 * i) % 32
01645         if ((32 - bitOffset) >= 9):
01646           if (dWordOffset << 2) > self.evt.cont_end:
01647             self.print_EOE_Warning()
01648             return -1
01649           pAccept[i] = (self.getDWord(dWordOffset) >> (32 - bitOffset - 9)) & 0x1FF
01650           self.evt.addTKRaccept(pAccept[i])
01651         else:
01652           if ((dWordOffset+1) << 2) > self.evt.cont_end:
01653             self.print_EOE_Warning()
01654             return -1
01655           pAccept[i] = (self.getDWord(dWordOffset)   << (9 - (32 - bitOffset)) & 0x1FF) | \
01656                        (self.getDWord(dWordOffset+1) >> (32 - (9 - (32 - bitOffset))))
01657           self.evt.addTKRaccept(pAccept[i])
01658     return p
01659 
01660   def evGetCAL_NumAccepts(self):
01661     """\brief Counts the number of hit calorimeter logs in the tower
01662     event contribution.
01663 
01664     Given a pointer to an entire TEM event contribution walk the data
01665     structure to the calorimeter log accepts word and return the sum of
01666     the number of hit logs.
01667 
01668     \return Number of hit logs
01669     """
01670     nAccepts = 0
01671     la = self.getDWord(self.evGetCAL_LogAccepts())
01672     for i in range(8):
01673       nAccepts = nAccepts + ((la >> (i<<2)) & 0xF)
01674     return nAccepts
01675 
01676   def evDumpGEM(self):
01677     """\brief Parses the GEM contribution by populating the data in self.evt.gem
01678 
01679     Requires calling evtCli.setCurrentContribution(EvtCli.GEM) before usage.
01680 
01681     """
01682     offset = self.evGetSummary() + 1
01683     val = self.getDWord(offset)
01684     self.evt.gem.ROI_Vector = (val >> 16)
01685     self.evt.gem.TKR_Vector = val & 0xFFFF
01686     val = self.getDWord(offset+1)
01687     self.evt.gem.CAL_HE_Vector = (val >> 16)
01688     self.evt.gem.CAL_LE_Vector = val & 0xFFFF
01689     val = self.getDWord(offset+2)
01690     self.evt.gem.triggerSummary = (val >> 16)
01691     self.evt.gem.deadzone = (self.evt.gem.triggerSummary >> 8)
01692     self.evt.gem.conditions = self.evt.gem.triggerSummary & 0xFF
01693     self.evt.gem.CNO_Vector = val & 0xFFFF
01694     self.evDumpGEM_Veto_List(offset+3)
01695     self.evt.gem.liveTime = self.getDWord(offset+7)
01696     self.evt.gem.prescaled = self.getDWord(offset+8)
01697     self.evt.gem.discarded = self.getDWord(offset+9)
01698     self.evt.gem.sent = self.getDWord(offset+10) # Deprecated
01699     self.evt.gem.condArrivalTimes.set(self.evt.gem.sent)
01700     self.evt.gem.triggerTime = self.getDWord(offset+11)
01701     self.evt.gem.onePPSTime = self.getDWord(offset+12)
01702     val = self.getDWord(offset+13)
01703     self.evt.gem.deltaOpenWindowTime = (val >> 16)
01704     self.evt.gem.deltaEventTime = val & 0xFFFF
01705 
01706     if self.__debugParserOutput:
01707       print "   ROI vector    = 0x%04x" % self.evt.gem.ROI_Vector
01708       print "   TKR vector    = 0x%04x" % self.evt.gem.TKR_Vector
01709       print "   CAL HE vector = 0x%04x" % self.evt.gem.CAL_HE_Vector
01710       print "   CAL LE vector = 0x%04x" % self.evt.gem.CAL_LE_Vector
01711       print "   Dead zone     = 0x%02x" % self.evt.gem.deadzone
01712       print "   Conditions    = 0x%02x" % self.evt.gem.conditions
01713       print "   CNO Vector    = 0x%04x" % self.evt.gem.CNO_Vector
01714       print "   Veto List:"
01715       print "     XZP, XZM    = 0x%04x, 0x%04x" % (self.evt.gem.vetoList.XZP,
01716                                                    self.evt.gem.vetoList.XZM)
01717       print "     YZP, YZM    = 0x%04x, 0x%04x" % (self.evt.gem.vetoList.YZP,
01718                                                    self.evt.gem.vetoList.YZM)
01719       print "     XY          = 0x%04x"         %  self.evt.gem.vetoList.XY
01720       print "     NA, RBN     = 0x%04x, 0x%04x" % (self.evt.gem.vetoList.NA,
01721                                                    self.evt.gem.vetoList.RBN)
01722       print "   Live time     = 0x%08x" % self.evt.gem.liveTime
01723       print "   Prescaled     = 0x%08x" % self.evt.gem.prescaled
01724       print "   Discarded     = 0x%08x" % self.evt.gem.discarded
01725       print "   Condition arrival:"
01726       print "     raw         = 0x%08x" % self.evt.gem.condArrivalTimes.ui
01727       print "     external    = 0x%02x" % self.evt.gem.condArrivalTimes.External
01728       print "     cno         = 0x%02x" % self.evt.gem.condArrivalTimes.CNO
01729       print "     calHE       = 0x%02x" % self.evt.gem.condArrivalTimes.CAL_HE
01730       print "     calLE       = 0x%02x" % self.evt.gem.condArrivalTimes.CAL_LE
01731       print "     tkr         = 0x%02x" % self.evt.gem.condArrivalTimes.TKR
01732       print "     roi         = 0x%02x" % self.evt.gem.condArrivalTimes.ROI
01733       print "   Trigger time  = 0x%08x" % self.evt.gem.triggerTime
01734       print "   One PPS time  = 0x%08x" % self.evt.gem.onePPSTime
01735       print "   Delta window open time = 0x%04x" % self.evt.gem.deltaOpenWindowTime
01736       print "   Delta event time       = 0x%04x" % self.evt.gem.deltaEventTime
01737       print
01738 
01739   def evDumpGEM_Veto_List(self, offset):
01740     """\brief Parses the Veto List block of the GEM contribution
01741 
01742     Used by evDumpGEM
01743 
01744     \param offset 32-bit word offset to the veto list block
01745 
01746     """
01747     veto = self.getDWord(offset)
01748     self.evt.gem.vetoList.XZP = (veto >> 16)
01749     self.evt.gem.vetoList.XZM = veto & 0xFFFF
01750     veto = self.getDWord(offset+1)
01751     self.evt.gem.vetoList.YZP = (veto >> 16)
01752     self.evt.gem.vetoList.YZM = veto & 0xFFFF
01753     self.evt.gem.vetoList.XY = self.getDWord(offset+2)
01754     veto = self.getDWord(offset+3)
01755     self.evt.gem.vetoList.NA = (veto >> 16)
01756     self.evt.gem.vetoList.RBN = veto & 0xFFFF
01757 
01758   def getWord(self,wordOffset):
01759     """\brief Unpack and return a 16-bit word value located at wordOffset
01760 
01761     \param  wordOffset Pointer to data
01762 
01763     \return            16-bit word value
01764     """
01765     result = self.unpack('!H',self.dat[(wordOffset<<1):((wordOffset+1)<<1)])
01766     if result != ():
01767       return result[0]
01768     else:
01769       return 0
01770 
01771   def getDWord(self,dWordOffset):
01772     """\brief Unpack and return a 32-bit word value located at dWordOffset
01773 
01774     \param  dWordOffset Pointer to data
01775 
01776     \return             32-bit word value
01777     """
01778     result = self.unpack('!L',self.dat[(dWordOffset<<2):((dWordOffset+1)<<2)])
01779     if result != ():
01780       return result[0]
01781     else:
01782       return 0
01783 
01784   def getByte(self,byteOffset):
01785     """\brief Unpack and return an 8-bit byte value located at byteOffset
01786 
01787     \param  byteOffset Pointer to data
01788 
01789     \return            8-bit byte value
01790     """
01791     result = self.unpack('B',self.dat[byteOffset])
01792     if result != ():
01793       return result[0]
01794     else:
01795       return 0
01796 
01797   def evGetCAL_Logs(self):
01798     """\brief Walks tower event contribution to the CAL log data.
01799 
01800     Given a pointer to an entire TEM event contribution walk the data
01801     structure to the beginning of the calorimeter log data.
01802 
01803     \return Offset to the beginning of the calorimeter log data
01804     """
01805     return self.evGetCAL_LogAccepts() + 1
01806 
01807   def evGetCAL_LogAccepts(self):
01808     """\brief Walks the tower event contribution to the calorimeter
01809     log accepts word.
01810 
01811     Given a pointer to an entire TEM event contribution walk the data
01812     structure returning a pointer to the calorimeter log accepts word.
01813 
01814     The 32-bit calorimeter log accepts word is immediately after the event
01815     summary word, i.e. the 2nd 32-bit word in the data.
01816 
01817     \return Offset to the calorimeter log accepts word.
01818     """
01819     return self.evGetSummary() + 1
01820 
01821   def evDumpCAL_LogAccepts(self):
01822     """\brief Decodes the log accepts word and stores it in evt.CAL_LogAccepts.
01823 
01824     """
01825     la = evCAL_LogAccepts(self.getCurrentContribution(), self.getDWord(self.evGetCAL_LogAccepts()))
01826     if self.__debugParserOutput:
01827       print("\n   CAL Log Accepts")
01828       # look for bogus accept values ( anything greater than 12 )
01829       for i in range(N_GCCC):
01830         if ((la.ui >> (i<<2)) & 0xF) > 12:
01831           print("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***")
01832           print("   *** Log accepts greater than 12.  This event is suspect     ***")
01833           print("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n")
01834 
01835       print("   ================================================")
01836       print("   GCCC   | GCCC_01 | GCCC_03 | GCCC_02 | GCCC_00 |")
01837       print("   -------+---------+---------+---------+---------+-------------")
01838       print("   layer  | y3   y2 | y1   y0 | x3   x2 | x1   x0 |  Raw")
01839       print("   -------+----+----+----+----+----+----+----+----+-------------")
01840       print("   hits   | %02d   %02d | %02d   %02d | %02d   %02d | %02d   %02d |  0x%08x" %
01841            (la.y3, la.y2, la.y1, la.y0, la.x3, la.x2, la.x1, la.x0, la.ui))
01842     self.evt.addCAL_LogAccept(la)
01843 
01844 
01845   def evDumpCAL_Logs(self):
01846     """\brief Decodes all the log data for the event and stores it in evt.CAL_LogData
01847 
01848     """
01849     la = evCAL_LogAccepts(0, self.getDWord(self.evGetCAL_LogAccepts()))
01850     if ( la.ui == 0 ):
01851       # nothing to decode
01852       return
01853 
01854     # get log data
01855     pLogData = self.evGetCAL_Logs()
01856 
01857     if self.__debugParserOutput:
01858       print("\n   CAL Log Data")
01859       print("   =====================================================")
01860       print("   -----   -----+------+------+------+------+-----------")
01861       print("   layer    Col   -Rng   -ADC   +Rng   +ADC   Raw")
01862       print("   -----   -----+------+------+------+------+-----------")
01863 
01864     twr = self.getCurrentContribution()
01865     if ( self.evt.summary.readout4 == 0):
01866       # regular read out
01867       # step through the 8 layers
01868       for i in range(8):
01869         nHitLogs = (la.ui >> (i<<2)) & 0xF
01870         if (nHitLogs):
01871           for j in range(nHitLogs):
01872             self.__dumpCAL_Log(twr, pLogData, i)
01873             pLogData = pLogData + 1
01874     else:
01875       # read out 4 range data
01876       # loop over accepts in groups of 2 -- 8 all together
01877       for i in range(4):
01878         # loop over 4 ranges
01879         for j in range(4):
01880           # loop over current 2 accepts
01881           for k in range(2):
01882             nHitLogs = (la.ui >> (((i<<1) + k)<<2)) & 0xF
01883             for l in range(nHitLogs):
01884               self.__dumpCAL_Log(twr, pLogData, ((i<<1) + k))
01885               pLogData = pLogData + 1
01886 
01887   def __dumpCAL_Log(self, twr, pLogData, layer):
01888     """\brief Decodes the log data
01889 
01890     \param pLogData Pointer to data from one accepted CAL log
01891     \param layer    Which layer the log data is a member of
01892 
01893     """
01894     if (pLogData<<2) > self.evt.cont_end:
01895       self.print_EOE_Warning()
01896     else:
01897       ld = evCAL_LogData(self.getDWord(pLogData))
01898       if self.__debugParserOutput:
01899         print("    %c%d       %02d    %d     %04x    %d     %04x   0x%08x" %
01900           (q(layer < 4,'x','y'), layer % 4,
01901           ld.column,
01902           ld.rangeADC_neg,
01903           ld.valADC_neg,
01904           ld.rangeADC_pos,
01905           ld.valADC_pos,
01906           ld.ui))
01907       self.evt.addCAL_LogData(twr, layer, ld)
01908 
01909 
01910   def evGetSummary(self):
01911     """\brief Return the offset to the summary word of the current contribution.
01912 
01913     In a contribution, first word after the header is the summary word
01914 
01915     \return Offset to the summary word of the current contribution
01916     """
01917     return self.evt.cont_offset + 1
01918 
01919   def __dumpTkrStrip(self, pAccepts, acceptArray):
01920     """\brief Decodes all TKR event strip data and stores it in evt.TKRstrips
01921 
01922     \param  pAccepts     Pointer to 32-bit aligned tracker event data
01923     \param  acceptArray  pointer to array of decoded tkr accept vectors
01924 
01925     \return              Number of strip hits
01926     """
01927     nStrip = 0
01928     if self.__debugParserOutput:
01929       print("\n   TKR Strips")
01930       print("   ========================================================")
01931       print("   GTCC  | GTRC | GTFE | Strip # | Raw      |")
01932       print("   ------+------+------+---------+----------+")
01933     stripData = evTKR_Strip(0)
01934     for i in range(N_GTCC):
01935       # foreach set bit in GTCC accept vector
01936       accept = acceptArray[i]
01937       for j in range(N_GTRC):
01938         if ( (accept >> (N_GTRC - 1 - j)) & 0x1):
01939           # walk strip data until done bit found
01940           done = 0
01941           while 1:
01942             stripData = self.evGetTKR_StripN(pAccepts, nStrip)
01943 
01944             if stripData.done != 0:
01945               stripData.done = 0
01946               done = 1
01947             self.evt.addTKRstrip(GTCC_MAP[i], j, stripData)
01948             nStrip = nStrip + 1
01949             if self.__debugParserOutput:
01950               print("    %d    |  %d   |  %02d  |   %02d    | 0x%03x    |" % (GTCC_MAP[i], j, stripData.gtfe, stripData.strip, stripData.ui))
01951             if done != 0: break
01952     return nStrip
01953 
01954   def evGetTKR_StripN(self, pAccepts, stripN, stripData=None):
01955     """\brief Fetches a 12-bit strip word from pAccepts, indexed by stripN.
01956 
01957     pAccepts points to the top of the accepts data ... the strip data
01958     starts 72 bits ( 8 * 9 ) from the beginning of accepts.  I.e. it
01959     starts 8 bits into the 3rd 32-bit word.
01960 
01961     \param  pAccepts  Pointer to 32-bit aligned tracker event data
01962     \param  stripN    The index of the 12-bit strip to fetch from pAccepts
01963     \param  stripData Optional argument, if passed, avoid creating the object
01964     \return          An evTKR_Strip object instance.
01965     """
01966     # Don't create the object if we are only counting, ie. called from evGetTKR_NumStrips()
01967     if stripData is None:
01968       stripData = evTKR_Strip(0)
01969     # skip the first two 32-bit words
01970     pAccepts = pAccepts + 2
01971     # each strip is 12 bits long.  the first strip starts 8 bits into the 32-bit word
01972     nBits = 8 + 12 * stripN
01973     dWordOffset = pAccepts + (nBits / 32)
01974     bitOffset = nBits % 32
01975     if ((32 - bitOffset) >= 12):
01976       if (dWordOffset<<2) > self.evt.cont_end:
01977         self.print_EOE_Warning()
01978         stripData.done = 1
01979       else:
01980         # all 12 bits are in this word
01981         stripData.ui = (self.getDWord(dWordOffset) >> (32 - bitOffset - 12)) & 0xFFF
01982     else:
01983       if ((dWordOffset+1)<<2) > self.evt.cont_end:
01984         self.print_EOE_Warning()
01985         stripData.done = 1
01986       else:
01987         # need to sew bits together across word boundary
01988         stripData.ui = (((self.getDWord(dWordOffset)   << ( 12 - ( 32 - bitOffset))) & 0xFFF) | \
01989                     (self.getDWord(dWordOffset+1) >> ( 32 - ( 12 - ( 32 - bitOffset)))))
01990     return stripData
01991 
01992 
01993   def __dumpTkrTOT(self, pAccepts, acceptArray, nStrip):
01994     """\brief Decodes all TKR event TOT data and stores them in evt.TKTtots
01995 
01996     \param pAccepts    Pointer to 32-bit aligned tracker event data
01997     \param acceptArray Pointer to array of decoded tkr accept vectors
01998     \param nStrip      Number of TKR strips decoded
01999 
02000     """
02001     if self.__debugParserOutput:
02002       print("\n   TKR TOT")
02003       print("   ========================================================")
02004       print("   GTCC  | GTRC | TOT    |")
02005       print("   ------+------+--------+")
02006 
02007     #determine where TOTs start -- count 8-bit bytes from the begining of the accepts
02008     #accepts bits = 9 bits * 8 GTCC = 72 bits = 9 bytes
02009     #strip bits   = 12 bits * nStrip = (12 bits * nStrip)/8 bytes
02010 
02011     #if nStrip is odd then we're on a nibble boundry -- add one more byte
02012 
02013     byteSkip = 9 + (( 12 * nStrip ) / 8)
02014     if ( nStrip & 0x1 ):
02015       byteSkip += 1
02016     # foreach GTCC
02017     for i in range(N_GTCC):
02018       # foreach set bit in GTCC accept vector
02019       for j in range(N_GTRC):
02020         if ( (acceptArray[i] >> (N_GTRC - j - 1)) & 0x1):
02021           # print TOT
02022           byteOffset = (pAccepts<<2) + byteSkip
02023           if byteOffset > self.evt.cont_end:
02024             self.print_EOE_Warning()
02025             return -1
02026           tot = self.getByte(byteOffset)
02027           if self.__debugParserOutput:
02028             print("    %d    |  %d   | 0x%02x   |"%(GTCC_MAP[i], j, tot))
02029           byteSkip += 1
02030           self.evt.addTKRtot(GTCC_MAP[i], j, tot)
02031 
02032   def evDumpTKR(self):
02033     """\brief Decodes all the TKR event data and stores it in the event object.
02034 
02035     """
02036     tkrAcpt = [0]*N_GTCC
02037     nAccept = 0
02038 
02039     p = self.evGetTKR_Accepts(tkrAcpt)
02040     if p == -1: return
02041     if self.__debugParserOutput:
02042       print("\n   TKR Accepts")
02043       print("   ========================================================")
02044       #   print("   Raw word 0:  0x%08x\n", p[0])
02045       #   print("   Raw word 1:  0x%08x\n", p[1])
02046       #   print("   Raw word 2:  0x%08x\n", p[2])
02047       print("   ========================================================")
02048       print("   GTCC  |  X/Y  |  L/R  |  E/O  |  Accepts    | Raw")
02049       print("   ------+-------+-------+-------+-------------+-----------")
02050     for i in range(N_GTCC):
02051       if self.__debugParserOutput:
02052         print("    %d    |   %c   | %5s | %4s  |  " % (GTCC_MAP[i],
02053               q(i < 4,'x','y'),
02054               q(((i == 1) | (i == 2) | (i == 4) | ( i == 7)),"right","left"),
02055               q(i % 2,"even","odd"))),
02056       bits = ""
02057       for j in range(N_GTRC):
02058         if ( (tkrAcpt[i] >> (N_GTRC - j - 1)) & 0x1):
02059           bits += "1"
02060           nAccept += 1
02061         else:
02062           bits += "0"
02063       if self.__debugParserOutput:
02064         print("\b%s  | 0x%03x"%(bits,tkrAcpt[i]))
02065     if self.__debugParserOutput:
02066       print("   ------+-------+-------+-------+-------------+-----------")
02067 
02068     if (nAccept != 0):
02069       # dump strip data
02070       nStrips = self.__dumpTkrStrip(p, tkrAcpt)
02071 
02072       # dump TOT data
02073       self.__dumpTkrTOT(p, tkrAcpt, nStrips)
02074 
02075   def evBitCount(self, x):
02076     """\brief Count the number of set bits in x
02077 
02078     \param  x 32-bit word value
02079 
02080     \return   Set bit count
02081     """
02082     count = 0
02083     for i in range(32):
02084       count = count + (( x >> i ) & 0x1)
02085     return count
02086 
02087 
02088   def evGetTKR_NumStrips(self):
02089     """Returns number of hit strips in the event
02090 
02091     \return Number of hit strips
02092     """
02093     nStrip = 0
02094     tkrAcpt = [0]*N_GTCC
02095 
02096     pAccepts = self.evGetTKR_Accepts(tkrAcpt)
02097     if pAccepts == -1: return
02098     stripData = evTKR_Strip(0)
02099     # foreach GTCC
02100     for i in range(N_GTCC):
02101       # foreach set bit in GTCC accept vector
02102       for j in range(N_GTRC):
02103         if ( (tkrAcpt[i] >> (N_GTRC - 1 - j)) & 0x1):
02104           # walk strip data until done bit found
02105           done = 0
02106           while not done:
02107             stripData = self.evGetTKR_StripN(pAccepts, nStrip, stripData)
02108             done = stripData.done
02109             nStrip += 1
02110     return nStrip
02111 
02112   def evGetTKR_TOT(self):
02113     """\brief Returns pointer to start of tracker TOT list
02114 
02115     \return Offset to the tracker TOT list
02116     """
02117     nStrips = self.evGetTKR_NumStrips()
02118 
02119     if nStrips == 0:
02120       return 0
02121 
02122 
02123     #  the TOTs come after the accepts (72-bits or 9 bytes) and after
02124     #  the strips ( 12-bits per strip ).  If the number of strips is odd
02125     #  we need to add one extra byte.
02126 
02127     pTOT = self.evGetTKR_Accepts(None) << 2
02128     pTOT += 9  # size of the accept words
02129     pTOT += (( 12 * nStrips ) / 8) # size of the strip words
02130     pTOT += (nStrips & 0x1)  # pad with one byte if number of strips is odd
02131     return pTOT
02132 
02133 
02134   def evGetTKR_NumAccepts(self):
02135     """\brief Counts the number of accepted TKR layer-ends.
02136 
02137     \return Number of accepted TKR layer-ends.
02138     """
02139     tkrAcpt = [0]*N_GTCC
02140     self.evGetTKR_Accepts(tkrAcpt)
02141 
02142     nBits = 0
02143     for i in range(N_GTCC):
02144       nBits += self.evBitCount(tkrAcpt[i])
02145     return nBits
02146 
02147 
02148   def evGetTEM_Diagnostic(self):
02149     """\brief Returns pointer to start of diagnostic event data.
02150 
02151     Caller should check the event summary word if a diagnostic
02152     contribution is present before calling this function.
02153 
02154     \return Offset to start of diagnostic event data
02155     """
02156     start = self.evGetTKR_Accepts(None) << 2
02157     nTkrAccepts = self.evGetTKR_NumAccepts()
02158     if nTkrAccepts == 0:
02159       # no tracker strip data, just skip over tracker accept data
02160       end = start + 9
02161     else:
02162       end = self.evGetTKR_TOT() # beginning of TOT data
02163       end += nTkrAccepts # one byte after the TOT data
02164 
02165     #  the diagnostic data comes after the tracker data and must be on a
02166     #  32-bit boundary
02167 
02168     offset = end - start
02169     #offset = offset + q((offset % 4), 4 - (offset % 4), 0)
02170     if (offset % 4):
02171       offset += (4 - (offset % 4))
02172     return ((start + offset) >> 2)
02173 
02174   def evGetTEM_Error(self):
02175     """\brief Returns pointer to the error word contribution of event data.
02176 
02177     Caller should check the event summary word if an error
02178     contribution is present before calling this function.
02179 
02180     \return Offset to the error word contribution
02181     """
02182     # the error contribution comes after the diagnostic contribution
02183     pErr = self.evGetTEM_Diagnostic()
02184     # check if we have a diagnostic contribution
02185     es = self.evt.summary
02186     if es.diag:
02187       # skip over diagnostic contribution
02188       pErr += (evDiag_Data.size >> 2)
02189     return pErr
02190 
02191 
02192   def __dumpErrGCCC(self, es, pErr, nWord, forcePrint=0):
02193     """\brief Decodes the GCCC error contribution.
02194 
02195     \param  es         Error summary 16-bit word
02196     \param  pErr       Pointer to 16-bit aligned tower event error contribution
02197     \param  nWord      Index into begining of error data
02198     \param  forcePrint If specified, dump the error even if in non-debug mode
02199 
02200     \return            Current offset into the error contribution
02201     """
02202     errSummary = es
02203 
02204     if self.__debugParserOutput or forcePrint: print
02205 
02206     # loop over 4 GCCC
02207     for gcccId in range(N_GCCC):
02208       # test summary bit for this GCCC
02209       if ( ( errSummary.gcccErr >> gcccId) & 0x1 ):
02210         # dump the error message
02211         idx = nWord
02212         nWord += 1
02213         errLen = self.getWord(pErr+idx)
02214         if self.__debugParserOutput or forcePrint:
02215           print("GCCC error word count %d" % errLen)
02216         # obtained "mapped GCCC" number
02217         mGCCC = GCCC_MAP[gcccId]
02218         #layer = q(( mGCCC % 2 ),'y','x')
02219         if (mGCCC % 2):
02220           layer = 'y'
02221         else:
02222           layer = 'x'
02223         while (errLen):
02224           errLen -= 1
02225           idx = nWord
02226           nWord += 1
02227           errGCCC = evErr_GCCC(self.getWord(pErr+idx))
02228           self.evt.addErrGCCCmsg(evErr_GCCC_Message(mGCCC, errGCCC))
02229           if errGCCC.errType == 0:
02230             # start bit missing
02231             if self.__debugParserOutput or forcePrint:
02232               print("   GCCC %d Start Bit Missing: raw ( 0x%04x )" % (mGCCC, errGCCC.ui))
02233           elif errGCCC.errType == 1:
02234             # parity error
02235             if self.__debugParserOutput or forcePrint:
02236               print("   GCCC %d Parity Error: raw ( 0x%04x )\n" % (mGCCC, errGCCC.ui))
02237           else:
02238             # unknown GCCC error message
02239             print("****************************************************")
02240             print("**")
02241             print("** Unknown GCCC error message type:  %d\n" % errGCCC.errType)
02242             print("** Raw value                      :  0x%04x" % errGCCC.ui)
02243             print("**")
02244             print("****************************************************")
02245             return nWord
02246           # both error types have the same display format
02247           if self.__debugParserOutput or forcePrint:
02248             print("   ================================================")
02249             print("   | %c%d- | %c%d- | %c%d+ | %c%d+ | Sweep | Type |" %
02250               (layer, q(( mGCCC % 2 ) , (mGCCC + 2)%4 , mGCCC + 1),
02251                layer, q(( mGCCC % 2 ) , (mGCCC + 1)%4 , mGCCC),
02252                layer, q(( mGCCC % 2 ) , (mGCCC + 2)%4 , mGCCC + 1),
02253                layer, q(( mGCCC % 2 ) , (mGCCC + 1)%4 , mGCCC)
02254               )
02255             )
02256             print("   ------+-----+-----+-----+-------+------+--------")
02257             print("   | %d%d  | %d%d  | %d%d  | %d%d  |   %d   |  %d   |" %
02258               ((errGCCC.errParm >> 7) & 0x1, (errGCCC.errParm >> 6) & 0x1,
02259                (errGCCC.errParm >> 5) & 0x1, (errGCCC.errParm >> 4) & 0x1,
02260                (errGCCC.errParm >> 3) & 0x1, (errGCCC.errParm >> 2) & 0x1,
02261                (errGCCC.errParm >> 1) & 0x1, (errGCCC.errParm     ) & 0x1,
02262                errGCCC.sweepNum, errGCCC.errType
02263               )
02264             )
02265             print("   ------------------------------------------------")
02266             print
02267     return nWord
02268 
02269 
02270   def __dumpErrGTCC(self, es, pErr, nWord, forcePrint=0):
02271     """\brief Decodes the GTCC error contribution.
02272 
02273     \param  es         Error summary 16-bit word
02274     \param  pErr       Pointer to 16-bit aligned tower event error contribution
02275     \param  nWord      Index into begining of error data
02276     \param  forcePrint If specified, dump the error even if in non-debug mode
02277 
02278     \return            Current offset into the error contribution
02279     """
02280     errSummary = es
02281 
02282     # loop over 8 GTCC
02283     for gtccId in range(N_GTCC):
02284       # test summary bit for this GTCC
02285       if ( ( errSummary.gtccErr >> gtccId) & 0x1 ):
02286         # dump the error message
02287         errLen = curErrLen = self.getWord(pErr+nWord)
02288         # loop over all errors
02289         while (curErrLen):
02290           curErrWords = 0
02291           errGTCCmsg = evErr_GTCC_Message()
02292           errGTCC = evErr_GTCC(self.getWord(pErr+nWord+curErrLen))
02293           errGTCCmsg.errGTCC = errGTCC
02294           errGTCCmsg.gtcc = GTCC_ERR_MAP[gtccId]
02295           self.evt.addErrGTCCmsg(errGTCCmsg)
02296           if self.__debugParserOutput or forcePrint:
02297             print
02298             print ("   GTCC %d, GTRC %d Error Message: raw ( 0x%04x )" %
02299                     ( errGTCCmsg.gtcc,
02300                       errGTCC.nGTRC,
02301                       errGTCC.ui
02302                     )
02303                   )
02304             print("   ================================================")
02305           # process error bits from LSB upto LSB
02306           if errGTCC.phsGTRC:
02307             # print GTRC error parameter from stack
02308             curErrWords+=1
02309             err = self.getWord(pErr+nWord+curErrLen-curErrWords)
02310             errGTCCmsg.parameters['PHS_GTRC'] = err
02311             if self.__debugParserOutput or forcePrint:
02312               print("   GTRC Phasing Error:   0x%04x" % err)
02313               print("   =============+=============")
02314               print("       Layer    |     Tag")
02315               print("   Rcvd   Expct | Rcvd   Expct")
02316               print("   =============+=============")
02317               print("    %02d     %02d   |  %d      %d" % ((err>>12) & 0xF, (err>>8) & 0xF, (err>>2) & 0x3, err & 0x3))
02318               print
02319           if ( errGTCC.phsGTFE):
02320             # print 5 GTFE error parameters from stack -- comes before
02321             # FIFO FULL error words if any.
02322             errGTCCmsg.parameters['PHS_GTFE'] = []
02323             for i in range(5):
02324               gtfePhs = self.getWord(pErr+nWord+curErrLen-curErrWords-5+i)
02325               errGTCCmsg.parameters['PHS_GTFE'].append(gtfePhs)
02326               if self.__debugParserOutput or forcePrint:
02327                 print("   GTFE Phasing Error:   0x%04x\n" % gtfePhs)
02328             curErrWords += 5
02329           if errGTCC.fifoFull:
02330             #  print 1 error parameter from stack -- last word on parameter stack, immediately
02331             #  before the error word.
02332             curErrWords+=1
02333             errGTCCmsg.parameters['FIFO_FULL'] = self.getWord(pErr+nWord+curErrLen-curErrWords)
02334             if self.__debugParserOutput or forcePrint:
02335               print("   FIFO Full Error:   0x%04x\n" % errGTCCmsg.parameters['FIFO_FULL'])
02336           if self.__debugParserOutput or forcePrint:
02337             if errGTCC.cblTimeOut:
02338                 print("   Cable Timeout Error")
02339             if errGTCC.hdrParity:
02340                 print("   Header Parity Error")
02341             if errGTCC.wrdCntParity:
02342                 print("   Word Count Parity Error")
02343             if errGTCC.GTRCsum:
02344                 print("   GTRC Summary Error")
02345             if errGTCC.dataParity:
02346                 print("   Data Parity Error")
02347           curErrLen -= curErrWords + 1
02348         if self.__debugParserOutput or forcePrint:
02349           print("   ------------------------------------------------")
02350           print
02351         nWord += errLen + 1
02352     return nWord
02353 
02354   def __dumpErrCablePhase(self, pErr, nWord, forcePrint=0):
02355     """\brief Decodes the cable phase error contribution.
02356 
02357     \param  pErr       Pointer to 16-bit aligned tower event error contribution
02358     \param  nWord      Index into begining of error data
02359     \param  forcePrint If specified, dump the error even if in non-debug mode
02360 
02361     \return            Current offset into the error contribution
02362     """
02363 
02364     # decode cable phase error structure
02365     cblPhs = evErr_CablePhase(self.getWord(pErr+nWord))
02366     self.evt.errCablePhase = cblPhs
02367     if self.__debugParserOutput or forcePrint:
02368       print("   Cable Controller Phasing Error: raw ( 0x%04x )" % cblPhs.ui)
02369       print("   ================================================")
02370       print("   GTCC |"),
02371     # loop over 8 GTCCs
02372       for i in range(N_GTCC):
02373         print("\b %d |" % GTCC_ERR_MAP[7 - i]),
02374       print
02375       print("   -----+"),
02376       # loop over 8 GTCCs
02377       for i in range(N_GTCC):
02378         print("\b---+"),
02379       print
02380       print("   Tag  |"),
02381       # loop over 8 GTCCs
02382       for i in range(N_GTCC):
02383         print("\b %d |" % (cblPhs.ui >> ((7-i) << 1) & 0x3)),
02384       print
02385       print("   ------------------------------------------------")
02386       print
02387 
02388     # increment past cable phase error
02389     return nWord+1
02390 
02391 
02392   def __dumpErrCableTimeOut(self, pErr, nWord, forcePrint=0):
02393     """\brief Decodes the cable timeout error contribution.
02394 
02395     \param  pErr       Pointer to 16-bit aligned tower event error contribution
02396     \parm   nWord      Index into begining of error data
02397     \param  forcePrint If specified, dump the error even if in non-debug mode
02398 
02399     \return            Current offset into the error contribution
02400     """
02401     cblTimeOut = evErr_CableTimeOut(self.getWord(pErr+nWord))
02402     self.evt.errCableTimeOut = cblTimeOut
02403     if self.__debugParserOutput or forcePrint:
02404       print("   Cable Time Out Error: raw ( 0x%04x )" % cblTimeOut.ui)
02405       print("   ================================================")
02406       print("   GCCC | "),
02407     # loop over 4 GCCCs
02408       for i in range(N_GCCC):
02409         if (cblTimeOut.ui >> i) & 0x1:
02410           print("\b%d  " % GCCC_MAP[i]),
02411       print
02412       print("   ------------------------------------------------")
02413       print("   GTCC | "),
02414     # loop over 8 GTCCs
02415       for i in range(N_GTCC):
02416         if (cblTimeOut.ui >> (i+4)) & 0x1:
02417           print("\b%d  " % GTCC_ERR_MAP[i]),
02418       print
02419       print("   ------------------------------------------------")
02420       print
02421 
02422     # increment past cable timeout error
02423     return nWord+1
02424 
02425 
02426   def evDumpTEM_Error(self, forcePrint=0):
02427     """\brief Decodes the event error contribution.
02428 
02429     If an error contribution is present this prints up to 20 16-bit
02430     words of the error contribution.
02431 
02432     \param  forcePrint If specified, dump the error even if in non-debug mode
02433     """
02434     errWord = 0
02435 
02436     # check if we have an error contribution
02437     es = self.evt.summary
02438     if ( es.error == 0):
02439       return 0
02440 
02441     pErr = self.evGetTEM_Error() << 1
02442     errVal = self.getWord(pErr+errWord)
02443     if errVal:
02444       if self.__debugParserOutput or forcePrint:
02445         print ("   Event Error Info")
02446         print ("   ================================================")
02447 
02448       if self.__debugParserOutput or forcePrint:
02449         # print 16-bit error words
02450         errPtr = pErr
02451         i = 0
02452         while errPtr < self.evt.cont_size / 2:
02453           print ("    raw %d: 0x%04x" % (i, self.getWord(errPtr)))
02454           errPtr = errPtr + 1
02455           i += 1
02456           if i > 20: break
02457         print
02458 
02459       # print error summary
02460       errSummary = evErr_Summary(errVal)
02461       self.evt.errSummary = errSummary
02462       if self.__debugParserOutput or forcePrint:
02463         print("   Error Summary: raw ( 0x%04x )" % errSummary.ui)
02464         print("   ================================================")
02465         print("   | cbl t/o | cbl phs |    TKR    |   CAL ")
02466         print("   ----------+---------+-----------+---------------")
02467       gtccErrBits = ""
02468       for i in range(N_GTCC):
02469         if ( (errSummary.gtccErr >> (7-i)) & 0x1):
02470           gtccErrBits = gtccErrBits + "1"
02471         else:
02472           gtccErrBits = gtccErrBits + "0"
02473       gcccErrBits = ""
02474       for i in range(4):
02475         if ( (errSummary.gcccErr >> (3-i)) & 0x1):
02476           gcccErrBits += "1"
02477         else:
02478           gcccErrBits += "0"
02479       if self.__debugParserOutput or forcePrint:
02480         print("   |    %d    |    %d    |  %s |  %s" % (errSummary.cblTimeOut, errSummary.cblPhsErr, gtccErrBits, gcccErrBits))
02481         print("   ------------------------------------------------")
02482 
02483       # increment error pointer past error summary word
02484       errWord += 1
02485 
02486       # error contributions are order as the LSB of the error summary,
02487       # i.e. the contributions come as: CAL, TKR, cable timeout, cable phase
02488 
02489       if errSummary.gcccErr:
02490         errWord = self.__dumpErrGCCC( errSummary, pErr, errWord, forcePrint)
02491       if errSummary.gtccErr:
02492         errWord = self.__dumpErrGTCC( errSummary, pErr, errWord, forcePrint)
02493       if errSummary.cblPhsErr:
02494         errWord = self.__dumpErrCablePhase( pErr, errWord, forcePrint)
02495       if errSummary.cblTimeOut:
02496         errWord = self.__dumpErrCableTimeOut( pErr, errWord, forcePrint)
02497 
02498       if self.__debugParserOutput or forcePrint:
02499         print("   ------------------------------------------------")
02500 
02501     return 0
02502 
02503   def __dumpCalDiag(self, diag):
02504     """\brief Decodes all the Calorimeter diagnostic info
02505 
02506     \param diag Pointer to event diagnostic data
02507     """
02508     print("   Calorimeter Diagnostic Data")
02509     print("   ================================================")
02510 
02511     for i in range(len(diag.cal)):
02512       print("                     layer %s    GCCC %d" % (diag.cal[i].layer, diag.cal[i].gccc ))
02513       print("               ----------------+-------------------")
02514       print("                Neg Layer-End  |  Pos Layer-End")
02515       print("               ----------------+-------------------")
02516       print("   Log Accepts "),
02517       nle_str = ""
02518       ple_str = ""
02519       for j in range(N_GCFE):
02520         if (diag.cal[i].negLayerEnd.logAccepts >> j) & 0x1:
02521           nle_str += "1"
02522         else:
02523           nle_str += "0"
02524       for j in range(N_GCFE):
02525         if (diag.cal[i].posLayerEnd.logAccepts >> j) & 0x1:
02526           ple_str += "1"
02527         else:
02528           ple_str += "0"
02529       print("%s   |  %s") % (nle_str, ple_str)
02530       print("               ----------------+-------------------")
02531       print("   Trg Low Eng         %d       |        %d" %
02532         (diag.cal[i].negLayerEnd.trgRequestLow, diag.cal[i].posLayerEnd.trgRequestLow))
02533       print("               ----------------+-------------------")
02534       print("   Trg High Eng        %d       |        %d" %
02535         (diag.cal[i].negLayerEnd.trgRequestHigh, diag.cal[i].posLayerEnd.trgRequestHigh))
02536       print("               ------------------------------------\n")
02537 
02538   def __dumpTkrDiag(self, diag):
02539     """\brief Decodes all the tracker diagnostic info
02540 
02541     \param diag Pointer to event diagnostic data
02542 
02543     """
02544     print("   Tracker Diagnostic Data")
02545     print("   =============================")
02546 
02547     print("   GTCC     | Trigger Request (GTRC)")
02548     print("   ---------+-------------------")
02549 
02550     for i in range(len(diag.tkr)):
02551       print("   GTCC_%d   | " % diag.tkr[i].gtcc),
02552       trq_str = ""
02553       for j in range(N_GTRC):
02554         if (diag.tkr[i].trgRequests >> (N_GTRC - 1 - j)) & 0x1:
02555           trq_str += "1"
02556         else:
02557           trq_str += "0"
02558       print("%s" % trq_str)
02559       print("   ---------+-------------------")
02560     print
02561 
02562   def evDumpDiagnostic(self):
02563     """\brief Decodes the event diagnostic contribution
02564 
02565     """
02566 
02567     # check if we have a diagnostic contribution
02568     es = self.evt.summary
02569     if es.diag == 0:
02570       return 0
02571 
02572     pDiag = self.evGetTEM_Diagnostic() << 1
02573     if pDiag:
02574       diag = evDiag_Data()
02575       for i in range(len(diag.cal)):
02576         diag.cal[i].gccc           = GCCC_MAP[i>>1]
02577         diag.cal[i].layer          = "%c%d" % (q(i<4,'x','y'), i%4)
02578         diag.cal[i].negLayerEnd.ui = self.getWord(pDiag)
02579         pDiag += 1
02580         diag.cal[i].posLayerEnd.ui = self.getWord(pDiag)
02581         pDiag += 1
02582       for i in range(len(diag.tkr)):
02583         diag.tkr[i].ui = self.getWord(pDiag)
02584         diag.tkr[i].gtcc = GTCC_MAP[i]
02585         pDiag += 1
02586       self.evt.diag = diag
02587       if self.__debugParserOutput:
02588         # print out the diagnostic
02589         print("\n   Event Diagnostic Info")
02590         print("   ================================================\n")
02591         self.__dumpCalDiag( diag)
02592         self.__dumpTkrDiag( diag)
02593         print("   End of Event Diagnostic Info")
02594         print("   ================================================")
02595         print
02596     return 1
02597 
02598   def evDumpSummary(self, minEvSize=24):
02599     """\brief Decodes the event summary word.
02600 
02601     Given a pointer to tower event contribution print the event summary word.
02602 
02603     \param minEvSize Minimum event size w/o error (default=24)
02604     """
02605     es = self.evt.summary
02606     print
02607     print("   Event Contribution Size (bytes): %d" % self.evt.cont_size)
02608     if self.evt.cont_size < minEvSize:
02609       print
02610       print("   *** WARNING *** WARNING *** WARNING *** WARNING ***")
02611       print("   *** Event size less than minimal bytes (%d)     ***" % minEvSize)
02612       print("   *** WARNING *** WARNING *** WARNING *** WARNING ***")
02613     print("   Event Contribution Source Addr : 0x%02x" % self.evt.contributor)
02614     print("   Event Contribution Summary Word: 0x%08x" % es.ui)
02615     print("   =====================================")
02616     print("   %-20s: %05d-%02d" % ("Event Number-Tag", es.evNumber, es.tag))
02617     print("   =====================================")
02618     print("   %-20s: %d" % ("Error", es.error))
02619     print("   %-20s: %d" % ("TRG Parity Error", es.trgParityErr))
02620     print("   =====================================")
02621     print("   %-20s: %d" % ("Diagnostic", es.diag))
02622     print("   %-20s: %d" % ("Cal Strobe", es.calStrobe))
02623     print("   %-20s: %d" % ("Readout 4", es.readout4))
02624     print("   %-20s: %d" % ("Zero suppress", es.zeroSuppress))
02625     print("   %-20s: %d" % ("TACK", es.TACK))
02626     print("   %-20s: %d" % ("Marker", es.marker))
02627 
02628     if es.error or es.trgParityErr:
02629       print
02630       print("   *** WARNING *** WARNING *** WARNING *** WARNING ***")
02631       print("   *** This event has errors -- See Summary Word   ***")
02632       print("   *** WARNING *** WARNING *** WARNING *** WARNING ***")
02633     return 0
02634 
02635   def __dumpAEMvec(self, cbl, type):
02636     """\brief Decodes the set bits specified by \a cbl and \a type
02637 
02638     This method is used by the old AEM event parser evDumpEventAEM_G2
02639 
02640     \param cbl  Which cable is being decoded
02641     \param type ACD vector type 1-veto, 2-zs
02642     """
02643     hitVect = self.evGetAEM_Vec(cbl, type)
02644     if self.__debugParserOutput:
02645       print("    %02d             " % cbl),
02646       for i in range(N_GAFE):
02647         print("%d" % ((hitVect >> i) & 0x1)),
02648       print("  0x%05x" % hitVect)
02649       print("   -----   ---------------------------------------------------------")
02650 
02651   def __dumpAEMlist(self, type):
02652     """\brief Decodes the list of hit vectors specified by \a type.
02653 
02654     This method is used by the old AEM event parser evDumpEventAEM_G2
02655 
02656     This function is used to decode the AEM Veto List and the AEM Accepts List.
02657 
02658     \param type ACD vector type
02659     """
02660     if self.__debugParserOutput:
02661       print("   -----   ---------------------------------------------------------")
02662       print("   Cable   Channel "),
02663       # number channels 17 down to 0
02664       for i in range(8):
02665         print("1"),
02666       for i in range(10):
02667         print("0"),
02668       print("  Raw")
02669       print("                   "),
02670       for i in range(17, -1, -1):
02671         print("%d" % (i % 10)),
02672       print
02673       print("   -----   ---------------------------------------------------------")
02674 
02675     # find i_th 18 bit word
02676     for i in range(N_GARC):
02677       self.__dumpAEMvec(i, type)
02678 
02679   def evDumpAEM_Vetos(self):
02680     """\brief Decodes the AEM veto hit list contribution
02681 
02682     This method is used by the old AEM event parser evDumpEventAEM_G2
02683 
02684     """
02685     if self.__debugParserOutput:
02686       print("\n   AEM Veto Hit Vectors")
02687       print("   =================================================================")
02688     self.__dumpAEMlist(AEM.EV_AEM_VETO)
02689     return 0
02690 
02691   def __getCblDataAEM(self, cbl):
02692     """\brief Returns pointer to AEM event data header for cable specified by \a cbl.
02693 
02694     This method is used by the old AEM event parser evDumpEventAEM_G2
02695 
02696     \param  cbl Which cable is being decoded
02697     \return     Offset to the AEM event data header
02698     """
02699     # the data begins one word after the event summary
02700     pCur = (self.evGetSummary() + 1) << 1
02701     while (cbl):
02702       # skip to the third word and test the "PHAs Follow" bit
02703       pCur += 2
02704       if self.getWord(pCur) & (0x1 <<10):
02705         # walk PHAs
02706         pCur += 1
02707         morePHAs = 1
02708         while (morePHAs):
02709           # check bit 15 for more PHAs
02710           morePHAs = self.getWord(pCur) & 0x4000
02711           pCur += 1
02712       else:
02713         pCur += 1
02714       cbl -= 1
02715     return pCur
02716 
02717   def evDumpAEM_Accepts(self):
02718     """\brief Decodes the AEM accept list contribution
02719 
02720     This method is used by the old AEM event parser evDumpEventAEM_G2
02721 
02722     """
02723     if self.__debugParserOutput:
02724       print("\n   AEM Accept Hit Vectors")
02725       print("   =================================================================")
02726     self.__dumpAEMlist(AEM.EV_AEM_ZEROSUP)
02727     return 0
02728 
02729   def evGetAEM_PHA(self, cbl):
02730     """\brief Returns pointer to start of AEM PHA values
02731 
02732     This method is used by the old AEM event parser evDumpEventAEM_G2
02733 
02734     \param cbl Which cable is being decoded
02735     """
02736     # fetch pointer to header for requested cable
02737     pHdr = self.__getCblDataAEM(cbl)
02738     # check "has PHA" bit is set
02739     if self.getWord(pHdr+2) & (0x1 << 10):
02740       # return pointer to first PHA value
02741       pPHA = pHdr+3
02742     else:
02743       pPHA = None
02744     return pPHA
02745 
02746   def evGetAEM_Vec(self, cbl, type):
02747     """\brief Returns the 18-bit vector for cable specified by \a cbl and \a type
02748 
02749     This method is used by the old AEM event parser evDumpEventAEM_G2
02750 
02751     \param  cbl  Which cable is being decoded
02752     \param  type ACD vector type
02753     \return      18-bit vector
02754 
02755     """
02756     # fetch pointer to header for requested cable
02757     pHdr = self.__getCblDataAEM(cbl)
02758 
02759     if ( type == AEM.EV_AEM_VETO):
02760       # decode veto vector
02761       vec = ((self.getWord(pHdr) << 3) | (self.getWord(pHdr+1) >> 13)) & 0x3FFFF
02762       self.evt.aem.vetoHitVectors[cbl] = vec
02763     elif ( type == AEM.EV_AEM_ZEROSUP ):
02764       # decode zero suppress vector
02765       vec = ((self.getWord(pHdr+1) << 5) | (self.getWord(pHdr+2) >> 11)) & 0x3FFFF
02766       self.evt.aem.acceptHitVectors[cbl] = vec
02767     else:
02768       vec = 0
02769 
02770     return vec
02771 
02772 
02773   def evDumpAEM_PHA(self):
02774     """\brief Decodes the AEM PHA contribution.
02775 
02776     This method is used by the old AEM event parser evDumpEventAEM_G2
02777 
02778     Given a pointer to AEM event contribution print the PHA values.
02779     """
02780     if self.__debugParserOutput:
02781       print("\n   AEM PHA Values")
02782       print("   ================================================================")
02783       print("   ** Warning:  This decoder assumes GARC register MAX_PHA = 18")
02784       print("   ** and GARC registers PHA_EN_0/1 = 0xFFFF.")
02785       print("   ================================================================\n")
02786       print("   ----+-----+-------+------------+--------------------")
02787       print("   Cbl   Rng    ADC    Parity Err    Raw")
02788       print("   ----+-----+-------+------------+--------------------")
02789 
02790     for cbl in range(N_GARC):
02791       # do we have any PHAs for this cable ?
02792       pRaw = self.evGetAEM_PHA(cbl)
02793       if pRaw != None:
02794         if ( self.getWord(pRaw) == 0 ):
02795           # null terminator PHA value -- go to next cable
02796           continue
02797         morePHAs = 1
02798         while (morePHAs):
02799           pha = evAEM_PHA(self.getWord(pRaw))
02800           self.evt.aem.addPHA(cbl, pha)
02801           pRaw += 1
02802           if self.__debugParserOutput:
02803             print("    %02d    %d    0x%03x      %d         0x%04x" % (cbl, pha.range, pha.ADC, pha.parityErr, pha.ui))
02804           # check bit 15 for more PHAs
02805           morePHAs = pha.more
02806 
02807     if self.__debugParserOutput:
02808       print("   ----------------------------------------------------\n")
02809 
02810     return 0
02811 
02812 
02813 # @fn       unsigned int evDumpEventAEM( unsigned int *pEv)
02814 # @param pEv pointer to 32-bit aligned AEM event contribution
02815 # @brief    Decodes the event contribution
02816 # @return   OK
02817 
02818   def evDumpEventAEM_G2(self):
02819     """\brief Given a pointer to AEM event contribution print its contents.
02820 
02821     This method is the old G2 compatible AEM event parser, please use the new
02822     event parser evDumpEventAEM for G3 based AEM events.
02823 
02824     """
02825     if self.__debugParserOutput:
02826       # minimum event size is 24
02827       self.evDumpSummary(24)
02828 
02829     self.evDumpAEM_Vetos()
02830     self.evDumpAEM_Accepts()
02831     self.evDumpAEM_PHA()
02832     # evDumpAEM_Error()
02833     return 0
02834 
02835 
02836   def evDumpEventAEM(self):
02837     """\brief The new AEM event parsing routine.
02838 
02839     This parser works according to the latest specs
02840     where not all cable contributions are guaranteed to
02841     be provided.
02842     """
02843     self.evt.aem.clearEvent()
02844     if self.__debugParserOutput:
02845       # minimum contribution size is 16
02846       self.evDumpSummary(16)
02847     # the data begins one word after the event summary
02848     pHdr = (self.evGetSummary() + 1) << 1
02849     endOfCables = 0
02850     while not endOfCables:
02851       # Skip to the third word to check end of cables and cable number
02852       cblHdr3 = self.getWord(pHdr+2)
02853       cblNo = (cblHdr3 >> 4) & 0xF
02854       endOfCables = (cblHdr3 >> 8) & 0x1
02855       # Check if there are no contributions
02856       if endOfCables and cblNo == 0xF:
02857         break
02858       # decode veto vector
02859       vec = ((self.getWord(pHdr) << 3) | (self.getWord(pHdr+1) >> 13)) & 0x3FFFF
02860       self.evt.aem.vetoHitVectors[cblNo] = vec
02861       # decode zero suppress vector
02862       vec = ((self.getWord(pHdr+1) << 5) | (self.getWord(pHdr+2) >> 11)) & 0x3FFFF
02863       self.evt.aem.acceptHitVectors[cblNo] = vec
02864       # check "has PHA" bit is set
02865       if cblHdr3  & (0x1 << 10):
02866         pPHA = pHdr + 3
02867         morePHAs = 1
02868         while (morePHAs):
02869           pha = evAEM_PHA(self.getWord(pPHA))
02870           self.evt.aem.addPHA(cblNo, pha)
02871           pPHA += 1
02872           morePHAs = pha.more
02873         pHdr = pPHA
02874       else:
02875         pHdr += 3
02876     if self.__debugParserOutput:
02877       # Dump the hit vectors
02878       for typ in (AEM.EV_AEM_VETO, AEM.EV_AEM_ZEROSUP):
02879         if typ == AEM.EV_AEM_VETO:
02880           print("\n   AEM Veto Hit Vectors")
02881         else:
02882           print("\n   AEM Accept Hit Vectors")
02883         print("   =================================================================")
02884         print("   -----   ---------------------------------------------------------")
02885         print("   Cable   Channel "),
02886         # number channels 17 down to 0
02887         for i in range(8):
02888           print("1"),
02889         for i in range(10):
02890           print("0"),
02891         print("  Raw")
02892         print("                   "),
02893         for i in range(17, -1, -1):
02894           print("%d" % (i % 10)),
02895         print
02896         print("   -----   ---------------------------------------------------------")
02897         cbl = 0
02898         if typ == AEM.EV_AEM_VETO:
02899           hitVect = self.evt.aem.vetoHitVectors
02900         else:
02901           hitVect = self.evt.aem.acceptHitVectors
02902         for vec in hitVect:
02903           print("    %02d             " % cbl),
02904           for i in range(N_GAFE):
02905             print("%d" % ((vec >> i) & 0x1)),
02906           print("  0x%05x" % vec)
02907           print("   -----   ---------------------------------------------------------")
02908           cbl += 1
02909 
02910       # Dump the PHA values
02911       print("\n   AEM PHA Values")
02912       print("   ================================================================")
02913       print("   ** Warning:  This decoder assumes GARC register MAX_PHA = 18")
02914       print("   ** and GARC registers PHA_EN_0/1 = 0xFFFF.")
02915       print("   ================================================================\n")
02916       print("   ----+-----+-------+------------+--------------------")
02917       print("   Cbl   Rng    ADC    Parity Err    Raw")
02918       print("   ----+-----+-------+------------+--------------------")
02919 
02920       cablesWithPHA = self.evt.aem.PHA.keys()
02921       cablesWithPHA.sort()
02922       for cbl in cablesWithPHA:
02923         phaVect = self.evt.aem.PHA[cbl]
02924         for pha in phaVect:
02925           print("    %02d    %d    0x%03x      %d         0x%04x" %
02926                    (cbl, pha.range, pha.ADC, pha.parityErr, pha.ui) )
02927       print("   ----------------------------------------------------\n")
02928 
02929 
02930   def print_EOE_Warning(self):
02931     """\brief Print warning if we have reached the end of the contribution prematurely
02932 
02933     """
02934     if self.__debugWarnings:
02935       log.error("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***")
02936       log.error("   *** Reached the end of event data while parsing             ***")
02937       log.error("   ***               This event is suspect                     ***")
02938       log.error("   *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***")
02939       logStack()
02940 

Generated on Fri Jul 21 13:26:28 2006 for LATTE R04-12-00 by doxygen 1.4.3