00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2005 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__ = "Minimal data taking application" 00012 __author__ = "S. Tuvi <Stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = ("$Date: 2005/04/14 21:16:01 $").split(' ')[1] 00014 __version__ = "$Revision: 1.1 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 import threading 00021 import logging as log 00022 import time 00023 00024 from LATTE.runcontrol.rcTransitions import rcTransitions 00025 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00026 00027 from support.SimpleGasuExample import * 00028 from support.MiniGLTExample import * 00029 00030 00031 # This class puts up a GUI for inputting a value of some sort. It is used by 00032 # the userApplication example to get the number of self triggers to take. 00033 class userArgument(ArgumentImpl): 00034 "GUI for getting the user to input some sort of value." 00035 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00036 ArgumentImpl.__init__(self, parent, name, modal, fl) 00037 self.__value = 0 00038 self.setCaption("Hello world!") 00039 00040 def OKButtonClicked(self): 00041 self.__value = int(self.ArgumentList.text().latin1()) 00042 self.close() 00043 00044 def CancelButtonClicked(self): 00045 self.__value = None 00046 self.close() 00047 00048 def getValue(self, caption): 00049 self.setCaption(caption) 00050 self.show() 00051 self.exec_loop() 00052 return self.__value 00053 00054 class userArgText(object): 00055 "Text user interface for getting the user to input some sort of value" 00056 def __init__(self): 00057 pass 00058 00059 def getValue(self, caption): 00060 return int(raw_input("%s: " % (caption))) 00061 00062 00063 # Example application implementation. 00064 # Note that the name of the class must be userApplication. 00065 # Look at rcTransitions for names of other transition methods that can be used. 00066 class userApplication(rcTransitions): 00067 "Implmentation class for a user application" 00068 def __init__(self, rc, userId, debug): 00069 rcTransitions.__init__(self, rc, userId, debug) 00070 log.debug("userApplication.__init__()") 00071 self.__eventSem = threading.Semaphore(0) 00072 self.__cmdSynchSem = threading.Semaphore(0) 00073 00074 def getName(self): 00075 return __name__ 00076 00077 def setup(self): 00078 log.debug("userApplication.setup()") 00079 00080 if self.rc is None: 00081 self.__arg = userArgText() 00082 else: 00083 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00084 00085 # Two choices for the trigger, GEM and MiniGLT 00086 if self.lat.existsGEM(): 00087 self.trigger( SimpleGasuExample() ) 00088 else: 00089 self.trigger( MiniGLTExample() ) 00090 00091 # A state transition can be rejected by not returning None 00092 return None 00093 00094 def startRun(self): 00095 log.debug("userApplication.startRun()") 00096 00097 caption = "Enter number of triggers to take" 00098 if self.rc is None: 00099 cnt = self.__arg.getValue(caption) 00100 else: 00101 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00102 00103 # The user pressed 'Cancel' 00104 if cnt is None: return -1 00105 self.__cnt = cnt 00106 00107 if self.rc is not None: 00108 self.getParameterVerifier().add(caption, cnt) 00109 00110 # Spawn a thread to synchronize commands with events 00111 self.__cmdSynchQuit = False 00112 00113 # A state transition can be rejected by not returning None 00114 return None 00115 00116 def stopRun(self): 00117 log.debug("userApplication.stopRun()") 00118 00119 if self.getBadEvents() == 0 and self.getErrorEvents() == 0: 00120 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00121 else: 00122 self.setCompletionStatus(self.COMPL_STATUS_FAILED) 00123 00124 self.__cmdSynchQuit = True 00125 self.__eventSem.release() 00126 00127 # The STOP_RUN transition can not be rejected 00128 00129 def resume(self): 00130 log.debug("userApplication.resume()") 00131 00132 # Issue self trigger to make up for the one that was lost during PAUSE 00133 self.trigger().solicit() 00134 00135 return None 00136 00137 def stop(self): 00138 log.debug("userApplication.stop()") 00139 00140 return self.stopRun() 00141 00142 def teardown(self): 00143 log.debug("userApplication.teardown()") 00144 # Allow the C++ object to be deleted 00145 if self.rc is not None and self.__arg is not None: 00146 self.__arg.deleteLater() 00147 00148 def process(self, (status, buffer)): 00149 "Method called back for each data event taken" 00150 #log.debug("userApplication.process()") 00151 00152 evtCli = self.evtCli 00153 00154 if status != 0: 00155 if evtCli.isGGLTStatus(): 00156 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00157 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00158 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00159 self.__eventSem.release() 00160 return 00161 try: 00162 # In the future this event may contain additional data 00163 if evtCli.isSweepEvent(): return 00164 except: 00165 # Event summary word inaccessible, handle the bad event here 00166 log.exception("") 00167 return 00168 00169 if self.lat.existsGEM(): 00170 if evtCli.setCurrentContribution(evtCli.GEM) != -1: 00171 evtCli.evDumpGEM() 00172 else: 00173 log.error("*******************************************") 00174 log.error("* NO GEM CONTRIBUTION PRESENT *") 00175 log.error("*******************************************") 00176 00177 if self.lat.TEMcnt() > 0: 00178 temId = self.lat.TEM[self.lat.TEM.keys()[0]].id() 00179 if evtCli.setCurrentContribution(temId) != -1: 00180 evtCli.evDumpCAL_LogAccepts() 00181 ###print "" 00182 evtCli.evDumpCAL_Logs(); 00183 #~ #print "" 00184 evtCli.evDumpTKR() 00185 evtCli.evDumpTEM_Error() 00186 evtCli.evDumpDiagnostic() 00187 #for acc in evtCli.evt.CAL_LogAccepts: 00188 # print "CAL Log Accept: 0x%08x" % acc.ui 00189 00190 #for layerLogData in evtCli.evt.CAL_LogData: 00191 # print "CAL Log Data: %s 0x%08x" % layerLogData.layer, layerLogData.data 00192 # sum = evtCli.evt.summary 00193 ###evtCli.evDumpSummary() 00194 00195 #for errorGCCC in evtCli.evt.errGCCCmsg: 00196 # errGCCC = errorGCCC.errGCCC 00197 # print "GCCC", errorGCCC.gccc, "Error:", hex(errGCCC.errParm), hex(errGCCC.sweepNum), hex(errGCCC.errType) 00198 00199 #for calDiag in evtCli.evt.diag.cal: 00200 # print calDiag.layer, calDiag.gccc, calDiag.negLayerEnd, calDiag.posLayerEnd 00201 #print 00202 #for tkrDiag in evtCli.evt.diag.tkr: 00203 # print tkrDiag.gtcc, tkrDiag.trgRequests 00204 else: 00205 log.error("*******************************************") 00206 log.error("* TEM CONTRIBUTION NOT PRESENT *") 00207 log.error("*******************************************") 00208 00209 # Get next event triggered 00210 self.__eventSem.release() 00211 00212 00213 #def __commandSynch(self, count): 00214 def commandSynch(self): 00215 "Method called by the command synchronization task" 00216 import time 00217 trigger = self.trigger() 00218 eventSem = self.__eventSem 00219 00220 # Drain the semaphore release count 00221 # Handles the case when the stop run release collided with a trigger release 00222 while eventSem.acquire(0): pass 00223 00224 t0 = time.time() 00225 00226 # Compensate for the extra CMD_SELF_TRIGGER below 00227 cnt = 1 00228 count = self.__cnt 00229 00230 # Wait for START_RUN to enable triggers 00231 trigger.waitForMaskEnable() 00232 00233 trigger.solicit() # Issue an internal trigger 00234 eventSem.acquire() # Wait for the event to be processed 00235 00236 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00237 while cnt < count and not self.__cmdSynchQuit: 00238 cnt += 1 00239 trigger.solicit() # Issue an internal trigger 00240 time.sleep(.0001) 00241 eventSem.acquire() # Wait for the event to be processed 00242 #trigger.disable() # Disable triggers 00243 # Do stuff 00244 #trigger.enable() # Enable triggers 00245 00246 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00247 00248 if t1 is None: 00249 t1 = t0 00250 if t2 is None: 00251 t2 = time.time() 00252 dT = t2 - t1 00253 if dT == 0.0: dT = 0.000001 00254 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00255 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00256 00257 # Get out of waiting when in suite or standalone mode 00258 self.sync() 00259 00260 # execute the GUI functions for stopRun, just in case 00261 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00262 if self.rc is not None: 00263 self.rc.doStop() 00264 00265 def wait(self): 00266 self.__cmdSynchSem.acquire() 00267 00268 def sync(self): 00269 if __name__ == "__main__" or self.isRunFromSuite(): 00270 self.__cmdSynchSem.release() 00271 00272 00273 # Standalone mode: 00274 if __name__ == "__main__": 00275 from LATTE.runcontrol.RunControlCommon import RunControlCommon 00276 00277 rcCommon = RunControlCommon() 00278 rcCommon.initialize() 00279 rcCommon.setLoggingLevel("INFO") 00280 rcCommon.connect() 00281 ua = userApplication(None, 321, rcCommon) 00282 ua.rcSetup() 00283 ua.rcStartRun() 00284 ua.wait() 00285 ua.rcStopRun() 00286 ua.rcTeardown()