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.6 $" 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 00095 # This class puts up a GUI for inputting a value of some sort. It is used by 00096 # the userApplication example to get the number of self triggers to take. 00097 class userArgument(ArgumentImpl): 00098 "GUI for getting the user to input some sort of value." 00099 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00100 ArgumentImpl.__init__(self, parent, name, modal, fl) 00101 self.__value = 0 00102 self.setCaption("Hello world!") 00103 00104 def OKButtonClicked(self): 00105 self.__value = int(self.ArgumentList.text().latin1()) 00106 self.close() 00107 00108 def CancelButtonClicked(self): 00109 self.__value = None 00110 self.close() 00111 00112 def getValue(self, caption): 00113 self.setCaption(caption) 00114 self.show() 00115 self.exec_loop() 00116 return self.__value 00117 00118 class userArgText(object): 00119 "Text user interface for getting the user to input some sort of value" 00120 def __init__(self): 00121 pass 00122 00123 def getValue(self, caption): 00124 return int(raw_input("%s: " % (caption))) 00125 00126 00127 # Example application implementation. 00128 # Note that the name of the class must be userApplication. 00129 # Look at rcTransitions for names of other transition methods that can be used. 00130 class userApplication(rcTransitions): 00131 "Implmentation class for a user application" 00132 def __init__(self, rc, userId, debug): 00133 rcTransitions.__init__(self, rc, userId, debug) 00134 log.debug("userApplication.__init__()") 00135 self.__eventSem = threading.Semaphore(0) 00136 self.__cmdSynchSem = threading.Semaphore(0) 00137 self.__lci = myLATcomponentIterator() 00138 self.__ldbi = LDF.LATdataBufferIterator(self.__lci) 00139 00140 def getName(self): 00141 return __name__ 00142 00143 def setup(self): 00144 log.debug("userApplication.setup()") 00145 00146 if self.rc is None: 00147 self.__arg = userArgText() 00148 else: 00149 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00150 00151 # Get a TEM instance 00152 if self.lat.TEMcnt() == 1: 00153 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00154 elif self.lat.TEMcnt() > 1: 00155 tem = self.lat.TEM.all() 00156 else: 00157 log.fatal("No TEM(s) found in the schema") 00158 return -1 00159 00160 if tem is not None: 00161 # clear TEM stats reg 00162 tem.COMMAND_RESPONSE = 0 00163 00164 # clear TEM status reg 00165 tem.STATUS = 0 00166 else: 00167 log.fatal("No TEM found in the schema: aborting...") 00168 return -1 00169 00170 ccc2 = tem.downCCC(2) # O$GCCC_02 00171 ccc2.LAYER_MASK_1 = 0x3BFD3FFFL 00172 00173 # Two choices for the trigger, GEM and MiniGLT 00174 if self.lat.existsGEM(): 00175 self.trigger( SimpleGasuExample() ) 00176 else: 00177 self.trigger( MiniGLTExample() ) 00178 00179 # A state transition can be rejected by not returning None 00180 return None 00181 00182 def startRun(self): 00183 log.debug("userApplication.startRun()") 00184 00185 caption = "Enter number of triggers to take" 00186 if self.rc is None: 00187 cnt = self.__arg.getValue(caption) 00188 else: 00189 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00190 00191 if cnt is None: return -1 00192 self.__cnt = cnt 00193 00194 # Spawn a thread to synchronize commands with events 00195 self.__cmdSynchQuit = False 00196 00197 # A state transition can be rejected by not returning None 00198 return None 00199 00200 def stopRun(self): 00201 log.debug("userApplication.stopRun()") 00202 00203 self.setCompletionStatus(self.COMPL_STATUS_SUCCESS) 00204 self.__cmdSynchQuit = True 00205 self.__eventSem.release() 00206 00207 # The STOP_RUN transition can not be rejected 00208 00209 def resume(self): 00210 log.debug("userApplication.resume()") 00211 00212 # Issue self trigger to make up for the one that was lost during PAUSE 00213 self.trigger().solicit() 00214 00215 return None 00216 00217 def stop(self): 00218 log.debug("userApplication.stop()") 00219 00220 return self.stopRun() 00221 00222 def teardown(self): 00223 log.debug("userApplication.teardown()") 00224 # Allow the C++ object to be deleted 00225 if self.rc is not None and self.__arg is not None: 00226 self.__arg.deleteLater() 00227 00228 def process(self, (status, buffer)): 00229 "Method called back for each data event taken" 00230 ##log.debug("userApplication.process()") 00231 00232 evtCli = self.evtCli 00233 00234 if status == 0: 00235 if 0: # One _OR_ the other method, not both 00236 self.__ldbi.iterate(buffer, len(buffer)) 00237 else: # Old way of doing things 00238 pass 00239 else: 00240 if evtCli.isGGLTStatus(): 00241 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00242 elif not evtCli.checkOnlineStatus(status, evtCli.PLAYBACK_ERROR): 00243 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00244 self.__eventSem.release() 00245 return 00246 00247 try: 00248 # In the future this event may contain additional data 00249 if evtCli.isSweepEvent(): return 00250 except: 00251 # Event summary word inaccessible, handle the bad event here 00252 log.exception("") 00253 return 00254 00255 print "Event Size =", evtCli.getEvtSize() 00256 print "Event Status =", evtCli.getEvtStatus() 00257 ts = evtCli.evGetTimestamp() 00258 print "Event Timestamp (GMT)=", time.asctime(time.gmtime(ts)), \ 00259 "and", int(math.modf(ts)[0]*1000), "ms" 00260 contList = evtCli.getContributionList() 00261 for cId in contList: 00262 evtCli.setCurrentContribution(cId) 00263 if cId.startswith('TEM'): 00264 evtCli.evDumpSummary() 00265 evtCli.evDumpCAL_LogAccepts() 00266 evtCli.evDumpCAL_Logs() 00267 evtCli.evDumpTKR() 00268 evtCli.evDumpTEM_Error() 00269 evtCli.evDumpDiagnostic() 00270 for acc in evtCli.evt.CAL_LogAccepts: 00271 print "CAL Log Accept: 0x%08x" % acc.ui 00272 00273 for logData in evtCli.evt.CAL_LogData: 00274 print "CAL Log Data: 0x%08x" % logData.data.ui 00275 elif cId == 'ACD': 00276 evtCli.evDumpSummary() 00277 evtCli.evDumpEventAEM() 00278 print "AEM Veto Hit Vectors:" 00279 j = 0 00280 for hitVect in evtCli.evt.aem.vetoHitVectors: 00281 print "\tCable %2d Raw Data 0x%05x" % (j, hitVect) 00282 j+=1 00283 print "\nAEM Accept Hit Vectors:" 00284 j = 0 00285 for hitVect in evtCli.evt.aem.acceptHitVectors: 00286 print "\tCable %2d Raw Data 0x%05x" % (j, hitVect) 00287 j+=1 00288 print "\nAEM PHA Values:" 00289 j = 0 00290 for pha in evtCli.evt.aem.PHA: 00291 print "\tPHA Value: 0x%04x" % pha 00292 00293 # Get next event triggered 00294 self.__eventSem.release() 00295 00296 #def __commandSynch(self, count): 00297 def commandSynch(self): 00298 "Method called by the command synchronization task" 00299 import time 00300 trigger = self.trigger() 00301 eventSem = self.__eventSem 00302 # Drain the semaphore release count 00303 # Handles the case when the stop run release collided with a trigger release 00304 while eventSem.acquire(0): pass 00305 00306 t0 = time.time() 00307 00308 # Compensate for the extra CMD_SELF_TRIGGER below 00309 cnt = 1 00310 count = self.__cnt 00311 00312 # Wait for START_RUN to enable triggers 00313 trigger.waitForMaskEnable() 00314 00315 trigger.solicit() # Issue an internal trigger 00316 eventSem.acquire() # Wait for the event to be processed 00317 00318 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00319 00320 while cnt < count and not self.__cmdSynchQuit: 00321 cnt += 1 00322 trigger.solicit() # Issue an internal trigger 00323 time.sleep(.0001) 00324 eventSem.acquire() # Wait for the event to be processed 00325 #trigger.disable() # Disable triggers 00326 # Do stuff 00327 #trigger.enable() # Enable triggers 00328 00329 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00330 # When we get here the triggers should still be enabled. 00331 # If the glt.MASK needs to be set through any other means 00332 # then it needs to be restored to its SETUP value here. 00333 00334 if t1 is None: 00335 t1 = t0 00336 if t2 is None: 00337 t2 = time.time() 00338 dT = t2 - t1 00339 if dT == 0.0: dT = 0.000001 00340 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00341 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00342 00343 # Get out of waiting when in suite or standalone mode 00344 self.sync() 00345 00346 # execute the GUI functions for stopRun, just in case 00347 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00348 if self.rc is not None: 00349 self.rc.doStop() 00350 00351 def wait(self): 00352 self.__cmdSynchSem.acquire() 00353 00354 def sync(self): 00355 if __name__ == "__main__" or self.isRunFromSuite(): 00356 self.__cmdSynchSem.release() 00357 00358 00359 # Standalone mode: 00360 if __name__ == "__main__": 00361 from LATTE.runcontrol.RunControlCommon import RunControlCommon 00362 00363 rcCommon = RunControlCommon() 00364 rcCommon.initialize() 00365 rcCommon.setLoggingLevel("DEBUG") 00366 rcCommon.connect() 00367 ua = userApplication(None, 321, rcCommon) 00368 ua.rcSetup() 00369 ua.rcStartRun() 00370 ua.wait() 00371 ua.rcStopRun() 00372 ua.rcTeardown()