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()