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