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