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