00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2003 00004 # by 00005 # The Board of Trustees of the 00006 # Leland Stanford Junior University. 00007 # All rights reserved. 00008 # 00009 00010 __facility__ = "Online" 00011 __abstract__ = "Example EBF event handling test application" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = "2/25/2003" 00014 __version__ = "$Revision: 1.8 $" 00015 __credits__ = "SLAC" 00016 00017 import LATTE.copyright_SLAC 00018 00019 import threading 00020 import logging as log 00021 from LATTE.runcontrol.rcTransitions import rcTransitions 00022 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00023 import time 00024 import math 00025 import sys 00026 00027 from support.SimpleGasuExample import * 00028 from support.MiniGLTExample import * 00029 00030 import LDF 00031 00032 import Numeric as Numeric 00033 00034 00035 def _unsigned(arg): 00036 """\brief Convert an unsigned int argument to an unsigned long 00037 00038 This funtion exists to help format unsigned ints greater than 0x7fffffff, 00039 which in Python 2.4 and up will be displayed as signed strings. 00040 """ 00041 return arg & (2L * sys.maxint + 1) 00042 00043 00044 class myLATcomponentIterator(LDF.LATcomponentIterator): 00045 def __init__(self): 00046 LDF.LATcomponentIterator.__init__(self) 00047 00048 def UDFcomponent(self, event, ebfContribution): 00049 print "" 00050 print "Undefined EBF component" 00051 return 0 00052 00053 def GLTcomponent(self, event, gemContribution): 00054 data = Numeric.fromstring(gemContribution.data(), 'i') 00055 print "GEM data: %08x %08x" % (_unsigned(data[0]), _unsigned(data[1])) 00056 print "Time = %f" % (gemContribution.timeFloat()) 00057 return 0 00058 00059 def ACDcomponent(self, event, aemContribution): 00060 print "ACD summary word = 0x%08x" % (aemContribution.summary()) 00061 print "ACD contribution length = %d" % (aemContribution.length()) 00062 data = Numeric.fromstring(aemContribution.data(), 'i') 00063 for i in range(aemContribution.payloadSize() >> 2): 00064 print "ACD data[%3d]: 0x%08x" % (i, _unsigned(data[i])) 00065 return 0 00066 00067 def CALcomponent(self, event, calContribution): 00068 print "CAL summary word = 0x%08x" % (calContribution.summary()) 00069 print "CAL contribution length = %d" % (calContribution.length()) 00070 print "CAL accepts = 0x%08x" % (calContribution.logAccepts()) 00071 data = Numeric.fromstring(calContribution.data(), 'i') 00072 for i in range(calContribution.numLogAccepts()): 00073 print "CAL Log Data[%3d]: 0x%08x" % (i, _unsigned(data[i])) 00074 00075 #evt = data[0:384] 00076 #evt.shape = (4,4,2,12) 00077 #evt = Numeric.swapaxes(evt,0,1) 00078 #evt = Numeric.resize(evt, (4,8,12)) 00079 return 0 00080 00081 def TKRcomponent(self, event, tkrContribution): 00082 print "TKR summary word = 0x%08x" % (tkrContribution.summary()) 00083 print "TKR contribution length = %d" % (tkrContribution.length()) 00084 array = 8*4*' ' # 8 longwords of space to receive accepts 00085 accepts = Numeric.fromstring(tkrContribution.acceptsMask(event, array), 'i') 00086 print "TKR accepts = 0x%03x 0x%03x 0x%03x 0x%03x 0x%03x 0x%03x 0x%03x 0x%03x" % \ 00087 (accepts[0], accepts[1], accepts[2], accepts[3], 00088 accepts[4], accepts[5], accepts[6], accepts[7]) 00089 data = Numeric.fromstring(tkrContribution.data(event), 'i') 00090 for i in range(tkrContribution.numAccepts(event)): 00091 print "TKR data[%3d]: 0x%08x" % (i, _unsigned(data[i])) 00092 return 0 00093 00094 # This class puts up a GUI for inputting a value of some sort. It is used by 00095 # the userApplication example to get the number of self triggers to take. 00096 class userArgument(ArgumentImpl): 00097 "GUI for getting the user to input some sort of value." 00098 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00099 ArgumentImpl.__init__(self, parent, name, modal, fl) 00100 self.__value = 0 00101 self.setCaption("Hello world!") 00102 00103 def OKButtonClicked(self): 00104 self.__value = int(self.ArgumentList.text().latin1()) 00105 self.close() 00106 00107 def CancelButtonClicked(self): 00108 self.__value = None 00109 self.close() 00110 00111 def getValue(self, caption): 00112 self.setCaption(caption) 00113 self.show() 00114 self.exec_loop() 00115 return self.__value 00116 00117 class userArgText(object): 00118 "Text user interface for getting the user to input some sort of value" 00119 def __init__(self): 00120 pass 00121 00122 def getValue(self, caption): 00123 return int(raw_input("%s: " % (caption))) 00124 00125 00126 # Example application implementation. 00127 # Note that the name of the class must be userApplication. 00128 # Look at rcTransitions for names of other transition methods that can be used. 00129 class userApplication(rcTransitions): 00130 "Implmentation class for a user application" 00131 def __init__(self, rc, userId, debug): 00132 rcTransitions.__init__(self, rc, userId, debug) 00133 log.debug("userApplication.__init__()") 00134 self.__eventSem = threading.Semaphore(0) 00135 self.__cmdSynchSem = threading.Semaphore(0) 00136 self.__lci = myLATcomponentIterator() 00137 self.__ldbi = LDF.LATdataBufferIterator(self.__lci) 00138 00139 def getName(self): 00140 return __name__ 00141 00142 def setup(self): 00143 log.debug("userApplication.setup()") 00144 00145 if self.isRunFromSuite(): 00146 self.setLastSuiteScript() 00147 self.__arg = None 00148 elif self.rc is None: 00149 self.__arg = userArgText() 00150 else: 00151 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00152 00153 # Get a TEM instance 00154 if self.lat.TEMcnt() == 1: 00155 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00156 elif self.lat.TEMcnt() > 1: 00157 tem = self.lat.TEM.all() 00158 else: 00159 log.fatal("No TEM(s) found in the schema") 00160 return -1 00161 00162 if tem is not None: 00163 # clear TEM stats reg 00164 tem.COMMAND_RESPONSE = 0 00165 00166 # clear TEM status reg 00167 tem.STATUS = 0 00168 else: 00169 log.fatal("No TEM found in the schema: aborting...") 00170 return -1 00171 00172 ccc2 = tem.downCCC(2) # O$GCCC_02 00173 ccc2.LAYER_MASK_1 = 0x3BFD3FFFL 00174 00175 # Two choices for the trigger, GEM and MiniGLT 00176 if self.lat.existsGEM(): 00177 self.trigger( SimpleGasuExample() ) 00178 else: 00179 self.trigger( MiniGLTExample() ) 00180 00181 # A state transition can be rejected by not returning None 00182 return None 00183 00184 def startRun(self): 00185 log.debug("userApplication.startRun()") 00186 00187 if self.isRunFromSuite(): 00188 cnt = 3 00189 else: 00190 caption = "Enter number of triggers to take" 00191 if self.rc is None: 00192 cnt = self.__arg.getValue(caption) 00193 else: 00194 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00195 00196 if cnt is None: return -1 00197 self.__cnt = cnt 00198 00199 # Spawn a thread to synchronize commands with events 00200 self.__cmdSynchQuit = False 00201 00202 # A state transition can be rejected by not returning None 00203 return None 00204 00205 def stopRun(self): 00206 log.debug("userApplication.stopRun()") 00207 00208 self.setCompletionStatus(self.COMPL_STATUS_SUCCESS) 00209 log.info("In %s: SESSION VAR=%s" % (self.getName(), self.getSessionVar("test"))) 00210 test = "e" 00211 self.setSessionVar("test", test) 00212 self.__cmdSynchQuit = True 00213 self.__eventSem.release() 00214 00215 # The STOP_RUN transition can not be rejected 00216 00217 def resume(self): 00218 log.debug("userApplication.resume()") 00219 00220 # Issue self trigger to make up for the one that was lost during PAUSE 00221 self.trigger().solicit() 00222 00223 return None 00224 00225 def stop(self): 00226 log.debug("userApplication.stop()") 00227 00228 return self.stopRun() 00229 00230 def teardown(self): 00231 log.debug("userApplication.teardown()") 00232 # Allow the C++ object to be deleted 00233 if self.rc is not None and self.__arg is not None: 00234 self.__arg.deleteLater() 00235 00236 def process(self, (status, buffer)): 00237 "Method called back for each data event taken" 00238 ###log.debug("userApplication.process()") 00239 00240 evtCli = self.evtCli 00241 00242 if status == 0: 00243 if 1: # One _OR_ the other method, not both 00244 self.__ldbi.iterate(buffer, len(buffer)) 00245 else: # Old way of doing things 00246 pass 00247 else: 00248 if evtCli.isGGLTStatus(): 00249 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00250 elif not evtCli.checkOnlineStatus(status, evtCli.PLAYBACK_ERROR): 00251 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00252 self.__eventSem.release() 00253 return 00254 00255 try: 00256 # In the future this event may contain additional data 00257 if evtCli.isSweepEvent(): return 00258 except: 00259 # Event summary word inaccessible, handle the bad event here 00260 log.exception("") 00261 return 00262 00263 print "Event Size =", evtCli.getEvtSize() 00264 print "Event Status =", evtCli.getEvtStatus() 00265 ts = evtCli.evGetTimestamp() 00266 print "Event Timestamp (GMT)=", time.asctime(time.gmtime(ts)), \ 00267 "and", int(math.modf(ts)[0]*1000), "ms" 00268 contList = evtCli.getContributionList() 00269 for cId in contList: 00270 evtCli.setCurrentContribution(cId) 00271 if cId.startswith('TEM'): 00272 evtCli.evDumpSummary() 00273 evtCli.evDumpCAL_LogAccepts() 00274 evtCli.evDumpCAL_Logs() 00275 evtCli.evDumpTKR() 00276 evtCli.evDumpTEM_Error() 00277 evtCli.evDumpDiagnostic() 00278 for acc in evtCli.evt.CAL_LogAccepts: 00279 print "CAL Log Accept: 0x%08x" % acc.ui 00280 00281 for logData in evtCli.evt.CAL_LogData: 00282 print "CAL Log Data: 0x%08x" % logData.data.ui 00283 elif cId == 'ACD': 00284 evtCli.evDumpSummary() 00285 evtCli.evDumpEventAEM() 00286 print "AEM Veto Hit Vectors:" 00287 j = 0 00288 for hitVect in evtCli.evt.aem.vetoHitVectors: 00289 print "\tCable %2d Raw Data 0x%05x" % (j, hitVect) 00290 j+=1 00291 print "\nAEM Accept Hit Vectors:" 00292 j = 0 00293 for hitVect in evtCli.evt.aem.acceptHitVectors: 00294 print "\tCable %2d Raw Data 0x%05x" % (j, hitVect) 00295 j+=1 00296 print "\nAEM PHA Values:" 00297 j = 0 00298 for pha in evtCli.evt.aem.PHA: 00299 print "\tPHA Value: 0x%04x" % pha 00300 00301 # Get next event triggered 00302 self.__eventSem.release() 00303 00304 #def __commandSynch(self, count): 00305 def commandSynch(self): 00306 "Method called by the command synchronization task" 00307 import time 00308 trigger = self.trigger() 00309 eventSem = self.__eventSem 00310 # Drain the semaphore release count 00311 # Handles the case when the stop run release collided with a trigger release 00312 while eventSem.acquire(0): pass 00313 00314 t0 = time.time() 00315 00316 # Compensate for the extra CMD_SELF_TRIGGER below 00317 cnt = 1 00318 count = self.__cnt 00319 00320 # Wait for START_RUN to enable triggers 00321 trigger.waitForMaskEnable() 00322 00323 trigger.solicit() # Issue an internal trigger 00324 eventSem.acquire() # Wait for the event to be processed 00325 00326 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00327 00328 while cnt < count and not self.__cmdSynchQuit: 00329 cnt += 1 00330 trigger.solicit() # Issue an internal trigger 00331 time.sleep(.0001) 00332 eventSem.acquire() # Wait for the event to be processed 00333 #trigger.disable() # Disable triggers 00334 # Do stuff 00335 #trigger.enable() # Enable triggers 00336 00337 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00338 # When we get here the triggers should still be enabled. 00339 # If the glt.MASK needs to be set through any other means 00340 # then it needs to be restored to its SETUP value here. 00341 00342 if t1 is None: 00343 t1 = t0 00344 if t2 is None: 00345 t2 = time.time() 00346 dT = t2 - t1 00347 if dT == 0.0: dT = 0.000001 00348 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00349 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00350 00351 # Get out of waiting when in standalone mode 00352 self.sync() 00353 00354 # execute the GUI functions for stopRun, just in case 00355 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00356 if self.rc is not None: 00357 self.rc.doStop() 00358 00359 def wait(self): 00360 self.__cmdSynchSem.acquire() 00361 00362 def sync(self): 00363 if __name__ == "__main__" or self.isRunFromSuite(): 00364 self.__cmdSynchSem.release() 00365 00366 00367 # Standalone mode: 00368 if __name__ == "__main__": 00369 from LATTE.runcontrol.RunControlCommon import RunControlCommon 00370 00371 rcCommon = RunControlCommon() 00372 rcCommon.initialize() 00373 rcCommon.setLoggingLevel("INFO") 00374 rcCommon.connect() 00375 ua = userApplication(None, 321, rcCommon) 00376 ua.rcSetup() 00377 ua.rcStartRun() 00378 ua.wait() 00379 ua.rcStopRun() 00380 ua.rcTeardown()