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__ = "Test application to demonstrate event merging" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = "6/29/2006" 00014 __updated__ = ("$Date: 2006/07/19 16:23:25 $").split(' ')[1] 00015 __version__ = "$Revision: 1.3 $" 00016 __release__ = "$Name: R04-12-00 $" 00017 __credits__ = "SLAC" 00018 00019 import LATTE.copyright_SLAC 00020 00021 import threading 00022 import time 00023 00024 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00025 from support.rcTransitionsBT import rcTransitionsBT 00026 00027 from LATTE.tests.apps.support.SimpleGasuExample import * 00028 from LATTE.tests.apps.support.MiniGLTExample import * 00029 00030 #from support.BTdump import testDG 00031 00032 00033 # This class puts up a GUI for inputting a value of some sort. It is used by 00034 # the userApplication example to get the number of self triggers to take. 00035 class userArgument(ArgumentImpl): 00036 "GUI for getting the user to input some sort of value." 00037 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00038 ArgumentImpl.__init__(self, parent, name, modal, fl) 00039 self.__value = 0 00040 self.setCaption("Hello world!") 00041 00042 def OKButtonClicked(self): 00043 self.__value = int(self.ArgumentList.text().latin1()) 00044 self.close() 00045 00046 def CancelButtonClicked(self): 00047 self.__value = None 00048 self.close() 00049 00050 def getValue(self, caption): 00051 self.setCaption(caption) 00052 self.show() 00053 self.exec_loop() 00054 return self.__value 00055 00056 class userArgText(object): 00057 "Text user interface for getting the user to input some sort of value" 00058 def __init__(self): 00059 pass 00060 00061 def getValue(self, caption): 00062 return int(raw_input("%s: " % (caption))) 00063 00064 00065 # Example application implementation. 00066 # Note that the name of the class must be userApplication. 00067 # Look at rcTransitions for names of other transition methods that can be used. 00068 class userApplication(rcTransitionsBT): 00069 "Implmentation class for a user application" 00070 def __init__(self, rc, userId, debug): 00071 rcTransitionsBT.__init__(self, rc, userId, debug) 00072 import logging 00073 logging.debug("userApplication.__init__()") 00074 self.__eventSem = threading.Semaphore(0) 00075 self.__cmdSynchSem = threading.Semaphore(0) 00076 00077 def getName(self): 00078 return __name__ 00079 00080 def setup(self): 00081 import logging 00082 logging.debug("userApplication.setup()") 00083 00084 if self.rc is None: 00085 self.__arg = userArgText() 00086 else: 00087 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00088 00089 # Get a TEM instance 00090 if self.lat.TEMcnt() == 1: 00091 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00092 elif self.lat.TEMcnt() > 1: 00093 tem = self.lat.TEM.all() 00094 else: 00095 import logging 00096 logging.fatal("No TEM(s) found in the schema") 00097 return -1 00098 00099 #----- The following RESETs and other system register manipulation is 00100 #----- commented out as it is handled by RunControl. Other register 00101 #----- setup should be taken care of in the schema/configuration file. 00102 # reset the TEM since we are going to modify DATA_MASKS 00103 #tem.CMD_RESET = 1 00104 00105 # clear TEM stats reg 00106 tem.COMMAND_RESPONSE = 0 00107 00108 # clear TEM status reg 00109 tem.STATUS = 0 00110 00111 # enable CAL, disable TKR, no diag # 0x10FF for diag 00112 #tem.DATA_MASKS = 0x10FF 00113 00114 # TEM config reg # set TEM timeout 00115 #tem.CONFIGURATION = 0 00116 00117 #status = gTEMread( __GT, temId, TEM_REG_CONFIGURATION, &payload); 00118 #printf("tem config reg = 0x%08x\n", payload); 00119 00120 # enable output in our GCCCs 00121 # broadcast load of GCCC_REG_CONFIGURATION 00122 00123 #bcast_ccc = tem.allCCC() 00124 #bcast_ccc.CONFIGURATION = 0x80000000L 00125 00126 # disable all GCRCs in all GCCCs via broadcast # GCCC_REG_LAYER_MASK_0, GCCC_REG_LAYER_MASK_1 00127 #bcast_ccc.LAYER_MASK_0 = 0xFFFFFFFFL 00128 #bcast_ccc.LAYER_MASK_1 = 0xFFFFFFFFL 00129 #ccc0 = tem.downCCC(0) # O$GCCC_00 00130 #ccc0.LAYER_MASK_0 = 0xFFFF0000L 00131 #ccc0.LAYER_MASK_1 = 0xFFFF000FL 00132 #ccc2 = tem.downCCC(2) # O$GCCC_02 00133 #ccc2.LAYER_MASK_0 = 0xFFFF0000L 00134 #ccc2.LAYER_MASK_1 = 0xFFFF0000L 00135 00136 # config GCFE for calibration -- range 0 first 00137 #bcast_cfe = tem.allCCC().allCRC().allCFE() 00138 #bcast_cfe.CONFIG_0 = 0x00 00139 #bcast_cfe.CONFIG_1 = 0x36 00140 #bcast_cfe.FLE_DAC = 0x55 00141 #bcast_cfe.FHE_DAC = 0x55 00142 #bcast_cfe.LOG_ACPT = 0x10 00143 #bcast_cfe.RNG_ULD_DAC = 0x7F 00144 #bcast_cfe.REF_DAC = 0x7f 00145 00146 # config GCRC for calibration 00147 #bcast_crc = tem.allCCC().allCRC() 00148 #bcast_crc.DELAY_1 = 0xFF 00149 #bcast_crc.DELAY_2 = 0xFF 00150 #bcast_crc.DELAY_3 = 0xFF 00151 #bcast_crc.DAC = 0x42FE 00152 #bcast_crc.DAC = 0x42FE 00153 00154 # large timeouts for all GCCCs 00155 # broadcast load of GCCC_REG_EVENT_TIMEOUTS 00156 #bcast_ccc.EVENT_TIMEOUTS = 0x0 00157 #status = gGCCCread( __GT, temId, 1, GCCC_REG_EVENT_TIMEOUTS, &payload); 00158 #printf("gccc register event timeouts = 0x%08x\n", payload); 00159 00160 # Register environment variables for housekeeping 00161 #hsk = self.getHSK() 00162 #regs = [tem.regs['data_masks'], ccc2.regs['layer_mask_1']] 00163 #hsk.addEnvRegs(regs) 00164 #hsk.setUpdateInterval(1) 00165 00166 # Two choices for the trigger, GEM and MiniGLT 00167 if self.lat.existsGEM(): 00168 self.trigger( SimpleGasuExample() ) 00169 else: 00170 self.trigger( MiniGLTExample() ) 00171 00172 # Override the default event handler 00173 self.selectEventHandler(rcTransitionsBT.EVENT_HANDLER_CUSTOM, self.eventHandler) 00174 00175 # A state transition can be rejected by not returning None 00176 return None 00177 00178 def startRun(self): 00179 import logging 00180 logging.debug("userApplication.startRun()") 00181 00182 # Don't let the Ancillary Trailer stop the run 00183 #self.autoStopRun(False) 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 # The user pressed 'Cancel' 00192 if cnt is None: return -1 00193 self.__cnt = cnt 00194 00195 self.getParameterVerifier().add(caption, cnt) 00196 00197 # Spawn a thread to synchronize commands with events 00198 self.__cmdSynchQuit = False 00199 00200 # A state transition can be rejected by not returning None 00201 return None 00202 00203 def stopRun(self): 00204 import logging 00205 logging.debug("userApplication.stopRun()") 00206 00207 if self.getBadEvents() == 0 and self.getErrorEvents() == 0: 00208 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00209 else: 00210 self.setCompletionStatus(self.COMPL_STATUS_FAILED) 00211 00212 self.__cmdSynchQuit = True 00213 self.__eventSem.release() 00214 00215 # The STOP_RUN transition can not be rejected 00216 00217 def resume(self): 00218 import logging 00219 logging.debug("userApplication.resume()") 00220 00221 # Issue self trigger to make up for the one that was lost during PAUSE 00222 self.trigger().solicit() 00223 00224 return None 00225 00226 def stop(self): 00227 import logging 00228 logging.debug("userApplication.stop()") 00229 00230 return self.stopRun() 00231 00232 def teardown(self): 00233 import logging 00234 logging.debug("userApplication.teardown()") 00235 # Allow the C++ object to be deleted 00236 if self.rc is not None and self.__arg is not None: 00237 self.__arg.deleteLater() 00238 00239 def process(self, (status, latDatagram)): 00240 "Method called back for each data event taken" 00241 import logging 00242 #logging.debug("userApplication.process()") 00243 00244 #evtCli = self.evtCli 00245 00246 if status != 0: 00247 #if evtCli.isGGLTStatus(): 00248 logging.error("%s.process(): GGLT_STATUS = 0x%08x = %d", self.getName(), status, status) 00249 #logging.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00250 #elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00251 # logging.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00252 # testDG(latDatagram) 00253 00254 # Get next event triggered 00255 self.__eventSem.release() 00256 00257 def commandSynch(self): 00258 "Method called by the command synchronization task" 00259 import time 00260 trigger = self.trigger() 00261 eventSem = self.__eventSem 00262 00263 # Drain the semaphore release count 00264 # Handles the case when the stop run release collided with a trigger release 00265 while eventSem.acquire(0): pass 00266 00267 t0 = time.time() 00268 00269 # Compensate for the extra CMD_SELF_TRIGGER below 00270 cnt = 1 00271 count = self.__cnt 00272 00273 # Wait for START_RUN to enable triggers 00274 trigger.waitForMaskEnable() 00275 00276 trigger.solicit() # Issue an internal trigger 00277 #eventSem.acquire() # Wait for the event to be processed 00278 00279 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00280 while cnt < count and not self.__cmdSynchQuit: 00281 cnt += 1 00282 trigger.solicit() # Issue an internal trigger 00283 time.sleep(.0001) 00284 eventSem.acquire() # Wait for the event to be processed 00285 #trigger.disable() # Disable triggers 00286 # Do stuff 00287 #trigger.enable() # Enable triggers 00288 00289 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00290 00291 if t1 is None: 00292 t1 = t0 00293 if t2 is None: 00294 t2 = time.time() 00295 dT = t2 - t1 00296 if dT == 0.0: dT = 0.000001 00297 import logging 00298 logging.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00299 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00300 00301 # Get out of waiting when in suite or standalone mode 00302 self.sync() 00303 00304 # execute the GUI functions for stopRun, just in case 00305 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00306 if self.rc is not None: 00307 self.rc.doStop() 00308 00309 def wait(self): 00310 self.__cmdSynchSem.acquire() 00311 00312 def sync(self): 00313 if __name__ == "__main__" or self.isRunFromSuite(): 00314 self.__cmdSynchSem.release() 00315 00316 00317 # Standalone mode: 00318 if __name__ == "__main__": 00319 import os 00320 import logging 00321 logging.basicConfig() 00322 logging.getLogger("").setLevel(logging.DEBUG) 00323 ua = userApplication(None, 321, 0) 00324 prefs = {'datasave': 1, 'datadir':os.path.join(os.environ['ONLINE_ROOT'],'temp')} 00325 ua.setPrefs(prefs) 00326 ua.rcSetup(os.path.join(os.environ['ONLINE_ROOT'], 'repos/simpleTemSchema.xml')) 00327 ua.rcStartRun() 00328 ua.wait() 00329 ua.rcStopRun() 00330 ua.rcTeardown() 00331 00332 # History: 00333 # $Log: testEvtBldr_script.py,v $ 00334 # Revision 1.3 2006/07/19 16:23:25 claus 00335 # AutoStopRun support 00336 # 00337 # Revision 1.2 2006/07/14 23:25:55 claus 00338 # Fix import problems 00339 # 00340 # Revision 1.1 2006/07/14 22:37:29 claus 00341 # Example socket based LATTE test script application of the event builder. 00342 # 00343 # Revision 1.1 2006/07/14 22:35:24 claus 00344 # Example socket based LATTE test script application of the event builder. 00345 # 00346 # Revision 1.7 2005/03/21 17:58:12 claus 00347 # Modified to use the first TEM found in the schema, if only one is there, or 00348 # broadcast to all TEMs if there are multiple. 00349 # 00350 # Revision 1.6 2004/11/01 23:09:39 claus 00351 # Added a comment. 00352 # 00353 # Revision 1.5 2004/10/30 01:52:20 stuvi 00354 # Check if the archiver is None before accessing it. 00355 # 00356 # Revision 1.4 2004/10/25 02:44:43 panetta 00357 # Fixes regarding byteswapping and error contribution 00358 # 00359 # Revision 1.3 2004/10/23 23:50:33 claus 00360 # Added completionStatus logic. 00361 # 00362 # Revision 1.2 2004/10/18 01:00:19 claus 00363 # Provided switch between 2 examples of adding custom LATcontributions. 00364 # 00365 # Revision 1.4 2004/08/31 03:13:38 stuvi 00366 # Integrated the parameter verifier with Run Control 00367 # 00368 # Revision 1.3 2004/08/18 18:00:15 stuvi 00369 # Updated for LATTE 4. 00370 # All hippo functions go through the Qt GUI bridge now. 00371 # 00372 # Revision 1.2 2004/08/13 04:46:22 claus 00373 # Got rid of obsolete TRUE and FALSE declarations. 00374 # 00375 # Revision 1.1 2004/07/28 21:24:00 stuvi 00376 # Added testAppCal and its supporting classes. 00377 # 00378 # Revision 1.28 2004/07/09 23:14:17 stuvi 00379 # Added "operatorobj" preference that contains the rcUser object and left the "operator" preference to contain the user name. 00380 # 00381 # Revision 1.27 2004/05/03 22:49:36 stuvi 00382 # Added commented out code example that demonstrates how to access the CAL and TKR diagnostics contributions. 00383 # 00384 # Revision 1.26 2004/05/03 21:19:47 stuvi 00385 # Moved non-Runcontrol scripts to the support directory and modified imports accordingly. 00386 # 00387 # Revision 1.25 2004/04/21 21:05:29 stuvi 00388 # Added an example of how to pass the preferences using the setPrefs method when running in standalone mode. 00389 # 00390 # Revision 1.24 2004/04/17 02:23:48 stuvi 00391 # Added teardown() to delete the C++ object for the userArgument 00392 # Fixed LogData parsing based on the evtCli changes 00393 # 00394 # Revision 1.23 2004/03/31 01:01:19 stuvi 00395 # Added commented code on how to parse the error contribution. 00396 # 00397 # Revision 1.22 2004/03/10 22:24:51 panetta 00398 # Upgraded trigger interface. 00399 # Removed dependencies on self.glt. 00400 # 00401 # Revision 1.21 2004/03/04 23:08:47 stuvi 00402 # Removed glt.destination assignment 00403 # 00404 # Revision 1.20 2004/02/20 03:20:23 stuvi 00405 # Added handling of the sweep events and error checking to the process() method, 00406 # 00407 # Revision 1.19 2004/02/13 03:13:25 stuvi 00408 # Sweep events are also sent to user script's process event now, so added code to handle the case. 00409 # 00410 # Revision 1.18 2004/02/02 23:14:00 stuvi 00411 # Changes required to make the scripts work with the new FSM engine. 00412 # 00413 # Revision 1.17 2004/01/30 04:33:44 claus 00414 # Updated for transitions not running in the GUI thread. 00415 # New commandSynch handling. 00416 # 00417 # Revision 1.16 2003/12/19 02:05:26 stuvi 00418 # Added support for creating and updating GUIs from a suite 00419 # 00420 # Revision 1.15 2003/12/11 02:22:35 stuvi 00421 # Suite and standalone mode modifications 00422 # 00423 # Revision 1.14 2003/12/11 01:53:16 stuvi 00424 # Modified code to support suites. 00425 # 00426 # Revision 1.13 2003/11/25 02:16:12 stuvi 00427 # Modified according to the current test setup to generate some results 00428 # 00429 # Revision 1.12 2003/11/04 04:25:11 stuvi 00430 # Changed the commandSynch logic so that the enableMask() call would not pose a threat to snapshot taking. 00431 # 00432 # Revision 1.11 2003/10/31 01:09:37 panetta 00433 # 1) Moved register writes from startRun to setup 00434 # 2) Added GLT enabling logic to __commandSynch 00435 # 3) Gave example of getting the start/stop time from the hardware/event stream 00436 # 00437 # Revision 1.10 2003/10/28 03:17:34 stuvi 00438 # Added support for calculating the event rate correctly using the new GLT behaviour. 00439 # 00440 # Revision 1.9 2003/08/21 21:13:38 stuvi 00441 # no message 00442 # 00443 # Revision 1.8 2003/07/17 00:01:35 stuvi 00444 # no message 00445 # 00446 # Revision 1.7 2003/06/13 23:26:24 stuvi 00447 # Added TEM reset 00448 # 00449 # Revision 1.6 2003/04/12 02:38:34 stuvi 00450 # Added Cancel button handler to argument class 00451 # 00452 # Revision 1.5 2003/04/09 00:45:15 stuvi 00453 # Commented out references to DATA_MASKS register which should not be touched during script execution. 00454 # 00455 # Revision 1.4 2003/04/01 21:04:59 stuvi 00456 # Fixed event count discrepancy when the run is stopped in the middle. 00457 # 00458 # Revision 1.3 2003/03/31 19:23:44 stuvi 00459 # Fixed name 00460 # 00461 # Revision 1.2 2003/03/26 21:59:36 stuvi 00462 # Fixed standalone mode 00463 # 00464 # Revision 1.1 2003/03/11 21:20:55 stuvi 00465 # Moved from RunControl directory 00466 # 00467 # Revision 1.8 2003/02/06 05:19:38 claus 00468 # Added resume; StopRun bug fix 00469 # 00470 # Revision 1.7 2003/02/06 04:14:35 claus 00471 # Fixed StopRun bug 00472 # 00473 # Revision 1.6 2002/12/11 21:18:07 stuvi 00474 # Changed glt register assignments to bit field assignments 00475 # 00476 # Revision 1.5 2002/12/10 01:09:58 claus 00477 # Added path and changed schema/config file for stand-alone mode 00478 # 00479 # Revision 1.4 2002/12/04 01:59:23 claus 00480 # Added message logging 00481 # 00482 # Revision 1.3 2002/12/02 17:17:09 claus 00483 # Added provision to allow application to run stand-alone 00484 # 00485 # Revision 1.2 2002/11/28 02:02:04 claus 00486 # Shuffled constructor arguments 00487 # 00488 # Revision 1.1 2002/11/27 05:02:48 claus 00489 # Initial version of Run Control 00490 #