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__ = "Example CAL test application" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = ("$Date: 2006/07/20 20:53:34 $").split(' ')[1] 00014 __version__ = "$Revision: 1.7 $" 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 from LATTE.runcontrol.rcTransitions import rcTransitions 00023 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00024 import time 00025 00026 from LATTE.trigger.TrgUsingTiles import TrgUsingTiles 00027 from LATTE.trigger.NullObjects import NoInputsEnabled 00028 from LATTE.trigger.rcTrgFunctions import rcTrgEngines 00029 from LATTE.trigger.TrgEngines import * 00030 from LATTE.trigger.rcTrgMiniGLT import rcTrgMiniGLT 00031 from LATTE.trigger.TrgMiniGLT import MiniGLTTrgConditionsValue 00032 from LATTE.trigger.TrgConditionsValue import * 00033 00034 import LDF 00035 import LDFdumper as LD 00036 00037 TRUE = (0 < 1) 00038 FALSE = not TRUE 00039 00040 ASC_CONTRIBUTION = 0x101f2010 00041 00042 # This class puts up a GUI for inputting a value of some sort. It is used by 00043 # the userApplication example to get the number of self triggers to take. 00044 class userArgument(ArgumentImpl): 00045 "GUI for getting the user to input some sort of value." 00046 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00047 ArgumentImpl.__init__(self, parent, name, modal, fl) 00048 self.__value = 0 00049 self.setCaption("Hello world!") 00050 00051 def OKButtonClicked(self): 00052 self.__value = int(self.ArgumentList.text().latin1()) 00053 self.close() 00054 00055 def CancelButtonClicked(self): 00056 self.__value = None 00057 self.close() 00058 00059 def getValue(self, caption): 00060 self.setCaption(caption) 00061 self.show() 00062 self.exec_loop() 00063 return self.__value 00064 00065 class userArgText(object): 00066 "Text user interface for getting the user to input some sort of value" 00067 def __init__(self): 00068 pass 00069 00070 def getValue(self, caption): 00071 return int(raw_input("%s: " % (caption))) 00072 00073 00074 # Example application implementation. 00075 # Note that the name of the class must be userApplication. 00076 # Look at rcTransitions for names of other transition methods that can be used. 00077 class userApplication(rcTransitions): 00078 "Implmentation class for a user application" 00079 def __init__(self, rc, userId, debug): 00080 rcTransitions.__init__(self, rc, userId, debug) 00081 log.debug("userApplication.__init__()") 00082 self.__eventSem = threading.Semaphore(0) 00083 self.__cmdSynchSem = threading.Semaphore(0) 00084 00085 self.__lci = LDF.LATcomponentIterator() 00086 self.__lconti = LDBI_LATcontributionIterator_(self.__lci) 00087 self.__ldbi = LDF.LATdataBufferIterator(self.__lconti) 00088 00089 def getName(self): 00090 return __name__ 00091 00092 def setup(self): 00093 log.debug("userApplication.setup()") 00094 00095 if self.rc is None: 00096 self.__arg = userArgText() 00097 else: 00098 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00099 00100 # Two choices for the trigger, GEM and MiniGLT 00101 if self.lat.existsGEM(): 00102 self.trigger( SimpleGasuExample() ) 00103 else: 00104 self.trigger( MiniGLTExample() ) 00105 00106 self.rc.common().getOCS().evtHandlerSendAcdScalers(1,0) 00107 00108 # A state transition can be rejected by not returning None 00109 return None 00110 00111 def startRun(self): 00112 log.debug("userApplication.startRun()") 00113 00114 caption = "Enter number of triggers to take" 00115 if self.rc is None: 00116 cnt = self.__arg.getValue(caption) 00117 else: 00118 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00119 00120 # The user pressed 'Cancel' 00121 if cnt is None: return -1 00122 self.__cnt = cnt 00123 00124 # Spawn a thread to synchronize commands with events 00125 self.__cmdSynchQuit = FALSE 00126 00127 # A state transition can be rejected by not returning None 00128 return None 00129 00130 def stopRun(self): 00131 log.debug("userApplication.stopRun()") 00132 00133 self.setCompletionStatus(rcTransitions.COMPL_STATUS_PASSED) 00134 self.__cmdSynchQuit = TRUE 00135 self.__eventSem.release() 00136 00137 # The STOP_RUN transition can not be rejected 00138 00139 def resume(self): 00140 log.debug("userApplication.resume()") 00141 00142 # Issue self trigger to make up for the one that was lost during PAUSE 00143 self.trigger().solicit() 00144 00145 return None 00146 00147 def stop(self): 00148 log.debug("userApplication.stop()") 00149 00150 return self.stopRun() 00151 00152 def teardown(self): 00153 log.debug("userApplication.teardown()") 00154 # Allow the C++ object to be deleted 00155 if self.gui is not None and self.__arg is not None: 00156 self.__arg.deleteLater() 00157 00158 def process(self, (status, buffer)): 00159 "Method called back for each data event taken" 00160 #log.debug("userApplication.process()") 00161 00162 evtCli = self.evtCli 00163 00164 if status != 0: 00165 if evtCli.isGGLTStatus(): 00166 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00167 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00168 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00169 self.__eventSem.release() 00170 return 00171 try: 00172 # In the future this event may contain additional data 00173 if evtCli.isSweepEvent(): 00174 print "SWEEP!!!" 00175 return 00176 except: 00177 # Event summary word inaccessible, handle the bad event here 00178 log.exception("") 00179 return 00180 00181 count = self.__ldbi.iterate(buffer, len(buffer)) 00182 00183 self.__eventSem.release() 00184 00185 00186 #def __commandSynch(self, count): 00187 def commandSynch(self): 00188 "Method called by the command synchronization task" 00189 import time 00190 trigger = self.trigger() 00191 eventSem = self.__eventSem 00192 00193 # Drain the semaphore release count 00194 # Handles the case when the stop run release collided with a trigger release 00195 while eventSem.acquire(0): pass 00196 00197 t0 = time.time() 00198 00199 # Compensate for the extra CMD_SELF_TRIGGER below 00200 cnt = 0 00201 count = self.__cnt 00202 00203 # Wait for START_RUN to enable triggers 00204 trigger.waitForMaskEnable() 00205 00206 while cnt < count and not self.__cmdSynchQuit: 00207 cnt += 1 00208 print "solicit" 00209 trigger.solicit() # Issue an internal trigger 00210 time.sleep(10) 00211 00212 # Get out of waiting when in suite or standalone mode 00213 self.sync() 00214 00215 # execute the GUI functions for stopRun, just in case 00216 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00217 if self.rc is not None: 00218 self.rc.doStop() 00219 00220 def wait(self): 00221 self.__cmdSynchSem.acquire() 00222 00223 def sync(self): 00224 if __name__ == "__main__" or self.isRunFromSuite(): 00225 self.__cmdSynchSem.release() 00226 00227 00228 class MiniGLTExample(rcTrgMiniGLT): 00229 """\brief MiniTower example interface to MiniGLT 00230 """ 00231 def __init__(self): 00232 """\brief AcdTriggerExample constructor 00233 """ 00234 rcTrgMiniGLT.__init__(self) 00235 self.__engines = MiniGLTTrgEngines() 00236 self.__conditions = MiniGLTSolicitedCondition() 00237 00238 def engines(self): 00239 """\brief Implementation of engines 'pure virtual' method from TrgAbstract 00240 """ 00241 return self.__engines 00242 00243 def conditions(self): 00244 """\brief Implementation of conditions 'pure virtual' method from TrgAbstract 00245 """ 00246 return self.__conditions 00247 00248 # implementaions of user-level trigger classes 00249 class MiniGLTTrgEngines(rcTrgEngines): 00250 def __init__(self): 00251 rcTrgEngines.__init__(self) 00252 # There are two engines in the MiniGLT. 00253 # 0) User defined engine 00254 # 15) Marker engine 00255 00256 eng = MiniGLTSolicitedEngine() 00257 self.replaceEngine(0,eng) 00258 00259 class MiniGLTSolicitedEngine(TrgEngine): 00260 """This class defines an engine which reads out the detector 00261 whenever there is a solicited trigger. 00262 This engine is not prescaled. 00263 """ 00264 def __init__(self): 00265 TrgEngine.__init__(self) 00266 self.__request = MarkerTrgReadout() 00267 def participate(self,conditionsValue): 00268 # This function relies on the programmer's knowledge that the 00269 # conditionsValue is a bitfield. 00270 cond = MiniGLTSolicitedCondition() 00271 condValue = cond.value() 00272 if conditionsValue & condValue: 00273 return True 00274 return False 00275 def prescale(self): 00276 return 0 00277 def request(self): 00278 return self.__request 00279 00280 class MiniGLTSolicitedCondition(MiniGLTTrgConditionsValue): 00281 """ Define a condition where only the CNO trigger is asserted 00282 """ 00283 def __init__(self): 00284 MiniGLTTrgConditionsValue.__init__(self) 00285 def solicited(self): 00286 return True 00287 00288 class MarkerTrgReadout(TrgReadout): 00289 """\brief MarkerTrgReadout class definition 00290 00291 Directs a module to send to its Front-End Electronics a command sequence 00292 which is composed only of the TACK command. This command will trigger 00293 a readout of the module's Front-End Electronics. 00294 Zero suppression is turned on. 00295 Marker is set to 1 00296 """ 00297 def __init__(self): 00298 """\brief TrgReadout constructor 00299 """ 00300 TrgReadout.__init__(self) 00301 00302 def zeroSuppress(self): return True 00303 def marker(self): return 1 00304 00305 00306 class LDBI_LATcontributionIterator_(LDF.LDBI_LATcontributionIterator): 00307 """\brief LDBI_LATcontributionIterator implementation 00308 00309 Reimplements virtual UDF contribution handler from LATcontributionIterator 00310 This implementation checks if the contribution ID corresponds to a 00311 ACD Software Counter contribution, and parses it out into summary, 00312 cno and tile pieces. If the contribution ID does not match the 00313 expected ID, an error message is given, and the parser returns -1, an 00314 error. 00315 """ 00316 def __init__(self, lci): 00317 LDF.LDBI_LATcontributionIterator.__init__(self, lci) 00318 def UDF(self, contrib, nextContrib): 00319 if contrib.identity().value() == ASC_CONTRIBUTION: 00320 print "Hey! I saw an ASC_CONTRIBUTION" 00321 import Numeric 00322 buffer = Numeric.fromstring(contrib.rawData(), 'i') 00323 00324 CNOstart = 16 00325 GECstart = CNOstart + 24 00326 00327 JJsummary = buffer[0:CNOstart] 00328 JJcnoCounts = buffer[CNOstart:GECstart] 00329 JJascHists = buffer[GECstart:] 00330 print "JJsummary: ", JJsummary 00331 # Now something needs to be done with these. 00332 00333 else: 00334 msg = "Unexpected LATcontribution id 0x%08x seen in event" % contrib.identity().value() 00335 log.error(msg) 00336 return -1 00337 00338 return 0 00339 00340 00341 class SimpleGasuExample(TrgUsingTiles): 00342 """\brief SimpleGASU example interface to GEM 00343 """ 00344 def __init__(self): 00345 """\brief SimpleGasuExample constructor 00346 """ 00347 TrgUsingTiles.__init__(self) 00348 self.__inputEnables = SGETrgInputEnables() 00349 self.__engines = SGETrgEngines() 00350 self.__conditions = FullCondition() 00351 00352 # Pure Virtual function implementation 00353 def conditions(self): 00354 return self.__conditions 00355 00356 def coincidences(self): 00357 """\brief Implementation of coincdences 'pure virtual' method from TrgUsingTiles 00358 """ 00359 # it just so happens that the roi is exactly the same as the coincidences object 00360 return self.roi() 00361 00362 def inputEnables(self): 00363 """\brief Implementation of inputEnables 'pure virtual' method from TrgAbstract 00364 """ 00365 return self.__inputEnables 00366 00367 def engines(self): 00368 """\brief Implementation of engines 'pure virtual' method from TrgAbstract 00369 """ 00370 return self.__engines 00371 00372 def useAcdAsTrigger(self): 00373 """Use ACD as a trigger source. 00374 """ 00375 return True 00376 00377 # implementaions of user-level trigger classes 00378 00379 class SGETrgInputEnables(NoInputsEnabled): 00380 """Class SGETrgInputEnables: 00381 Empty Input enables. 00382 """ 00383 def __init__(self): 00384 NoInputsEnabled.__init__(self) 00385 00386 00387 class SGETrgEngines(rcTrgEngines): 00388 """Class MyTrgEngines: 00389 Initialize the trigger engines list class. 00390 """ 00391 def __init__(self): 00392 rcTrgEngines.__init__(self) 00393 eng1 = SolicitedEngine() 00394 eng2 = FullEngine() 00395 self.replaceEngine(0,eng1) 00396 self.replaceEngine(1,eng2) 00397 00398 class SolicitedEngine(TrgEngine): 00399 """This class defines an engine which reads out the detector 00400 whenever there is a solicited trigger. 00401 This engine is not prescaled. 00402 """ 00403 def __init__(self): 00404 TrgEngine.__init__(self) 00405 self.__request = MarkerTrgReadout() 00406 def participate(self,conditionsValue): 00407 # This function relies on the programmer's knowledge that the 00408 # conditionsValue is a bitfield. 00409 cond = SolicitedCondition() 00410 if conditionsValue & cond.value(): 00411 return True 00412 return False 00413 def prescale(self): 00414 return 0 00415 def request(self): 00416 return self.__request 00417 00418 class SolicitedCondition(TrgConditionsValue): 00419 """ Define a condition where only the solicited trigger is asserted 00420 """ 00421 def __init__(self): 00422 TrgConditionsValue.__init__(self) 00423 def solicited(self): 00424 return True 00425 00426 class FullCondition(TrgConditionsValue): 00427 """ Define a condition where only the solicited trigger is asserted 00428 """ 00429 def __init__(self): 00430 TrgConditionsValue.__init__(self) 00431 def solicited(self): return True 00432 def roi(self): return True 00433 def calLow(self): return True 00434 def calHigh(self): return True 00435 def tkr(self): return True 00436 def periodic(self): return True 00437 def cno(self): return True 00438 def external(self): return True 00439 00440 class FullEngine(TrgEngine): 00441 def __init__(self): 00442 TrgEngine.__init__(self) 00443 self.__request = TrgReadout() 00444 def participate(self,conditionsValue): 00445 # This function relies on the programmer's knowledge that the 00446 # conditionsValue is a bitfield. 00447 cond = FullCondition() 00448 if conditionsValue & cond.value(): 00449 return True 00450 return False 00451 def prescale(self): return 0 00452 def request(self): return self.__request