00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2002 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 TKR test application" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = ("$Date: 2005/03/31 02:55:06 $").split(' ')[1] 00014 __version__ = "$Revision: 1.6 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 00021 import threading 00022 import sys 00023 00024 from LATTE.runcontrol.rcTransitions import rcTransitions 00025 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00026 00027 from sihippo import * 00028 import logging as log 00029 import time 00030 00031 import LDF 00032 00033 from support.SimpleGasuExample import * 00034 from support.MiniGLTExample import * 00035 00036 00037 def _unsigned(arg): 00038 """\brief Convert an unsigned int argument to an unsigned long 00039 00040 This funtion exists to help format unsigned ints greater than 0x7fffffff, 00041 which in Python 2.4 and up will be displayed as signed strings. 00042 """ 00043 return arg & (2L * sys.maxint + 1) 00044 00045 00046 class myTKRcontributionIterator(LDF.TKRcontributionIterator): 00047 def __init__(self, hists): 00048 LDF.TKRcontributionIterator.__init__(self) 00049 self.__hists = hists 00050 00051 def strip(self, tower, layerEnd, hit): 00052 self.__hists[0].addRow([hit]) 00053 00054 def TOT(self, tower, layerEnd, tot): 00055 self.__hists[1].addRow([tot]) 00056 00057 class myLATcomponentIterator(LDF.LATcomponentIterator): 00058 def __init__(self, hists): 00059 LDF.LATcomponentIterator.__init__(self) 00060 self.__tkrIterator = myTKRcontributionIterator(hists) 00061 00062 def CALcomponent(self, event, calContribution): 00063 return 0 00064 00065 def TKRcomponent(self, event, contribution): 00066 self.__tkrIterator.iterateStrips(event, contribution) 00067 self.__tkrIterator.iterateTOTs(contribution) 00068 00069 return 0 00070 00071 00072 # This class puts up a GUI for inputting a value of some sort. It is used by 00073 # the userApplication example to get the number of self triggers to take. 00074 class userArgument(ArgumentImpl): 00075 "GUI for getting the user to input some sort of value." 00076 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00077 ArgumentImpl.__init__(self, parent, name, modal, fl) 00078 self.__value = 0 00079 self.setCaption("Hello world!") 00080 00081 def OKButtonClicked(self): 00082 self.__value = int(self.ArgumentList.text().latin1()) 00083 self.close() 00084 00085 def getValue(self, caption): 00086 self.setCaption(caption) 00087 self.show() 00088 self.exec_loop() 00089 return self.__value 00090 00091 class userArgText(object): 00092 "Text user interface for getting the user to input some sort of value" 00093 def __init__(self): 00094 pass 00095 00096 def getValue(self, caption): 00097 return int(raw_input("%s: " % (caption))) 00098 00099 00100 # Example application implementation. 00101 # Note that the name of the class must be userApplication. 00102 # Look at rcTransitions for names of other transition methods that can be used. 00103 class userApplication(rcTransitions): 00104 "Implmentation class for a user application" 00105 def __init__(self, gui, userId, debug): 00106 rcTransitions.__init__(self, gui, userId, debug) 00107 print "userApplication.__init__()" 00108 self.__eventSem = threading.Semaphore(0) 00109 self.__cmdSynchSem = threading.Semaphore(0) 00110 00111 self.gui.execGUImethod(self.__initHippo) 00112 00113 self.__lci = myLATcomponentIterator(self.__hists) 00114 self.__ldbi = LDF.LATdataBufferIterator(self.__lci) 00115 00116 00117 def getName(self): 00118 return "hTestAppEvt" 00119 00120 def setup(self): 00121 print "userApplication.setup()" 00122 00123 if self.rc is None: 00124 self.__arg = userArgText() 00125 else: 00126 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00127 00128 # Get a TEM instance 00129 if self.lat.TEMcnt() == 1: 00130 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00131 elif self.lat.TEMcnt() > 1: 00132 tem = self.lat.TEM.all() 00133 else: 00134 log.fatal("No TEM(s) found in the schema") 00135 return -1 00136 00137 tcc = tem.allTCC() 00138 00139 # 00140 # Configure GTRCs 00141 # 00142 00143 # our board is connected CC = 2, RC = 0 and CC = 3, RC = 0 00144 # reset GTRC # required before all triggers 00145 00146 trc = tcc.allTRC() 00147 00148 trc.CMD_RESET = 1 00149 00150 # number of GTFE to readout left 00151 nGTFEsLeft = 7 00152 nGTFEsRight = 0 00153 00154 # max hits per GTRC # 31 max 00155 maxHits = 31 00156 00157 enMask = 0x6 00158 00159 dLO = (enMask << 28) | ((nGTFEsRight << 7)& 0xF80) | (maxHits & 0x7F); 00160 print "dLO=", dLO, hex(dLO) 00161 00162 # cable controller 2, readout controller 0 00163 tcc = tem.downTCC(2) 00164 trc = tcc.downTRC(1) 00165 00166 trc.CSR = dLO 00167 00168 dLO = (enMask << 28) | ((nGTFEsLeft << 7)& 0xF80) | (maxHits & 0x7F); 00169 print "dLO=", dLO, hex(dLO) 00170 00171 # cable controller 3, readout controller 0 00172 tcc = tem.downTCC(3) 00173 trc = tcc.downTRC(1) 00174 00175 trc.CSR = dLO 00176 00177 # 00178 # Configure GTFEs 00179 # 00180 00181 tfe = trc.allTFE() 00182 tfe.TRIG_MASK = 0x0 00183 tfe.DATA_MASK = 0x0 00184 tfe.CALIB_MASK = 0x0 00185 tfe.DAC = 0x00001902 00186 # configure front ends # all listen to left 00187 tfe.MODE = 0 00188 #tfe = trc.downTFE(0) 00189 00190 # configure default DACs for threshold and calibration 00191 # Calibration DAC Range and Resolution 00192 # Low Range (B6=0): DAC output voltage in mV = 1.57 + 1.53*DAC_Value 00193 # High Range (B6=1): DAC output voltage in mV = 15.0 + 14.6*DAC_Value 00194 # Discriminator Threshold DAC Range and Resolution 00195 # Low Range (B6=0): DAC output voltage in mV = 4.5 + 4.5*DAC_Value 00196 # High Range (B6=1): DAC output voltage in mV = 12.9 + 12.9*DAC_Value 00197 00198 00199 # calRng = 1 00200 # thrRng = 0 00201 # calDAC = 60 00202 # thrDAC = 10 00203 00204 tfe.DAC = 0x00001952 # based on the above Rng and DAC values 00205 00206 # enable GTFE for data taking # all channels 00207 tfe.TRIG_MASK = 0xffffffffffffffff 00208 tfe.DATA_MASK = 0xffffffffffffffff 00209 00210 # Cal strobe channels 4 and 48 only 00211 tfe.CALIB_MASK = 0x0001000000000010 00212 00213 #~ #Mask of the following Registers 00214 #~ tfe = trc.downTFE(13) 00215 #~ tfe.DATA_MASK = 0x0L 00216 #~ tfe.CALIB_MASK = 0x0L 00217 #~ tfe.TRIG_MASK = 0x0L 00218 00219 #~ tfe = trc.downTFE(14) 00220 #~ tfe.DATA_MASK = 0x0L 00221 #~ tfe.CALIB_MASK = 0x0L 00222 #~ tfe.TRIG_MASK = 0x0L 00223 00224 #~ tfe = trc.downTFE(19) 00225 #~ #tfe.DATA_MASK = 0x0L 00226 #~ tfe.CALIB_MASK = 0x0L 00227 #~ tfe.TRIG_MASK = 0x0L 00228 00229 #~ tfe = trc.downTFE(20) 00230 #~ #tfe.DATA_MASK = 0x0L 00231 #~ tfe.CALIB_MASK = 0x0L 00232 #~ tfe.TRIG_MASK = 0x0L 00233 00234 # Two choices for the trigger, GEM and MiniGLT 00235 if self.lat.existsGEM(): 00236 self.trigger( SimpleGasuExample() ) 00237 else: 00238 self.trigger( MiniGLTExample() ) 00239 00240 # A state transition can be rejected by not returning None 00241 return None 00242 00243 def startRun(self): 00244 log.debug("userApplication.startRun()") 00245 00246 caption = "Enter number of triggers to take" 00247 if self.gui is None: 00248 cnt = self.__arg.getValue(caption) 00249 else: 00250 cnt = self.gui.execGUImethod(self.__arg.getValue, caption) 00251 # Allow the C++ object to be deleted 00252 self.__arg.deleteLater() 00253 00254 # The user pressed 'Cancel' 00255 if cnt is None: return -1 00256 self.__cnt = cnt 00257 00258 self.gui.execGUImethod(self.__initPlots) 00259 self.__cmdSynchQuit = False 00260 00261 # A state transition can be rejected by not returning None 00262 return None 00263 00264 def stopRun(self): 00265 self.setCompletionStatus(self.COMPL_STATUS_SUCCESS) 00266 self.__cmdSynchQuit = True 00267 self.__eventSem.release() 00268 00269 # The STOP_RUN transition can not be rejected 00270 00271 def resume(self): 00272 # Issue self trigger to make up for the one that was lost during PAUSE 00273 self.trigger().solicit() 00274 00275 return None 00276 00277 def stop (self): 00278 return self.stopRun() 00279 00280 def process(self, (status, buffer)): 00281 "Method called back for each data event taken" 00282 ##log.debug("userApplication.process()") 00283 00284 evtCli = self.evtCli 00285 00286 if status != 0: 00287 if evtCli.isGGLTStatus(): 00288 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00289 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00290 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00291 self.__eventSem.release() 00292 return 00293 try: 00294 # In the future this event may contain additional data 00295 if evtCli.isSweepEvent(): return 00296 except: 00297 # Event summary word inaccessible, handle the bad event here 00298 log.exception("") 00299 return 00300 00301 self.__ldbi.iterate(buffer, len(buffer)) 00302 00303 self.__hists[2].addRow([evtCli.getEvtSize()]) #event.length()]) 00304 00305 # Get next event triggered 00306 self.__eventSem.release() 00307 00308 00309 def commandSynch(self): 00310 "Method called by the command synchronization task" 00311 trigger = self.trigger() 00312 eventSem = self.__eventSem 00313 t0 = time.time() 00314 cnt = 0 00315 count = self.__cnt 00316 00317 # Wait for START_RUN to enable triggers 00318 trigger.waitForMaskEnable() 00319 00320 while cnt < count and not self.__cmdSynchQuit: 00321 cnt = cnt + 1 00322 trigger.solicit() # Issue an internal trigger 00323 eventSem.acquire() # Wait for the event to be processed 00324 time.sleep(.001) 00325 00326 wc = WindowController.instance() 00327 canvas = wc.currentCanvas() 00328 canvas.setIntervalEnabled ( 0 ) 00329 dT = time.time() - t0 00330 if dT == 0.0: dT = 0.000001 00331 print "%s processed %d events in %.3f seconds = %.1f events/second" % \ 00332 (self.getName(), cnt, dT, self.evtCnt/dT) 00333 00334 # Get out of waiting when in suite or standalone mode 00335 self.sync() 00336 00337 # execute the GUI functions for stopRun, just in case 00338 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00339 if self.rc is not None: 00340 self.rc.doStop() 00341 00342 def wait(self): 00343 self.__cmdSynchSem.acquire() 00344 00345 def sync(self): 00346 if __name__ == "__main__" or self.isRunFromSuite(): 00347 self.__cmdSynchSem.release() 00348 00349 def __initHippo(self): 00350 self.__label = [0, 0, 0] 00351 self.__label[0] = ['Strip Hits'] 00352 self.__label[1] = ['TOTs'] 00353 self.__label[2] = ['Event Size'] 00354 ntc = NTupleController.instance() 00355 self.__hists = [0, 0, 0] 00356 self.__hists[0] = ntc.createNTuple(1) 00357 self.__hists[1] = ntc.createNTuple(1) 00358 self.__hists[2] = ntc.createNTuple(1) 00359 self.__hists[0].setTitle('TKR Event Strip Readout') 00360 self.__hists[1].setTitle('TKR Event TOT Readout') 00361 self.__hists[2].setTitle('Event length') 00362 self.__hists[0].setLabels(self.__label[0]) 00363 self.__hists[1].setLabels(self.__label[1]) 00364 self.__hists[2].setLabels(self.__label[2]) 00365 if __name__ == "__main__": 00366 ## app = HDApp() 00367 ## canvas = app.canvas() 00368 app = QApplication ( sys.argv ) 00369 canvas = CanvasWindow() 00370 canvas.show() 00371 else: 00372 wc = WindowController.instance() 00373 canvas = wc.currentCanvas() 00374 ## already done by main applicaton: canvas.show() 00375 ## ntuple_list = [0.0] 00376 ## self.__nt.addRow(ntuple_list) 00377 ## self.__nt2.addRow(ntuple_list) 00378 00379 ## see new way below 00380 ## hist = Display('Histogram',self.__nt,'Strip Hits') 00381 ## hist2 = Display('Histogram',self.__nt2,'Event 00382 00383 def __initPlots(self): 00384 wc = WindowController.instance() 00385 canvas = wc.currentCanvas() 00386 canvas.clear() 00387 self.__hists[0].clear() 00388 self.__hists[1].clear() 00389 self.__hists[2].clear() 00390 dc = DisplayController.instance() 00391 hist1 = dc.createDisplay ( 'Histogram', self.__hists[0], self.__label[0] ) 00392 hist2 = dc.createDisplay ( 'Histogram', self.__hists[1], self.__label[1] ) 00393 hist3 = dc.createDisplay ( 'Histogram', self.__hists[2], self.__label[2] ) 00394 canvas.addDisplay(hist1) 00395 canvas.addDisplay(hist2) 00396 canvas.addDisplay(hist3) 00397 self.__hists[0].setIntervalCount ( 2000 ) 00398 self.__hists[1].setIntervalCount ( 1000 ) 00399 self.__hists[2].setIntervalCount ( 400 ) 00400 canvas.setIntervalEnabled ( 0 ) 00401 canvas.show() 00402 canvas.setIntervalEnabled ( 1 ) 00403 00404 #Standalone mode: 00405 if __name__ == "__main__": 00406 import sys 00407 from qt import * 00408 from sihippo import * 00409 00410 ua = userApplication(None, 321, 0) 00411 ua.rcSetup('../repos/simpleTemSchema.xml') 00412 ua.rcStartRun() 00413 ua.wait() 00414 ua.rcStopRun() 00415 ua.rcTeardown() 00416 raw_input("Press any key to end") 00417 00418 # History: 00419 # $Log: hTestAppEvt.py,v $ 00420 # Revision 1.6 2005/03/31 02:55:06 stuvi 00421 # Fixed TRCs according to Selim's teststand. 00422 # 00423 # Revision 1.5 2005/03/30 06:04:33 stuvi 00424 # Removed configuration settings which should normally come from the schema. 00425 # 00426 # Revision 1.4 2005/03/21 17:58:11 claus 00427 # Modified to use the first TEM found in the schema, if only one is there, or 00428 # broadcast to all TEMs if there are multiple. 00429 # 00430 # Revision 1.3 2004/10/22 20:32:48 stuvi 00431 # Fixed log.exception() 00432 # 00433 # Revision 1.2 2004/08/18 18:00:15 stuvi 00434 # Updated for LATTE 4. 00435 # All hippo functions go through the Qt GUI bridge now. 00436 # 00437 # Revision 1.1 2004/08/07 02:14:33 stuvi 00438 # no message 00439 # 00440 # Revision 1.8 2004/07/15 22:58:35 stuvi 00441 # Added waitForMaskEnable 00442 # 00443 # Revision 1.7 2004/05/03 21:19:46 stuvi 00444 # Moved non-Runcontrol scripts to the support directory and modified imports accordingly. 00445 # 00446 # Revision 1.6 2004/04/17 02:22:17 stuvi 00447 # Various Hippo related fixes 00448 # Added teardown() to delete the C++ object for the userArgument 00449 # 00450 # Revision 1.5 2004/04/08 03:16:44 stuvi 00451 # Added canvas clearing. 00452 # 00453 # Revision 1.4 2004/04/08 01:48:42 claus 00454 # Reworked to work with LDF. 00455 # 00456 # Revision 1.3 2004/04/07 22:20:51 stuvi 00457 # no message 00458 # 00459 # Revision 1.2 2004/03/10 22:24:50 panetta 00460 # Upgraded trigger interface. 00461 # Removed dependencies on self.glt. 00462 # 00463 # Revision 1.1 2004/01/30 04:39:53 claus 00464 # Test application to histogram data from EBF events. 00465 # This is not yet working. 00466 # 00467 # Revision 1.9 2003/01/12 19:45:41 pfkeb 00468 # Move interval counting to ntuple 00469 # 00470 # Revision 1.8 2003/01/08 00:22:21 pfkeb 00471 # New interface to NTupleController 00472 # 00473 # Revision 1.7 2003/01/06 23:57:21 claus 00474 # Merged Ric's changes with Paul's 00475 # 00476 # Revision 1.6 2003/01/05 00:18:50 pfkeb 00477 # Make use of new HippoDraw features 00478 # 00479 # Revision 1.5 2002/12/23 19:00:25 pfkeb 00480 # Add HippoDraw to RunControl 00481 # 00482 # Revision 1.4 2002/12/19 19:59:52 claus 00483 # Mods for Hippo 00484 # 00485 # Revision 1.3 2002/12/11 21:18:07 stuvi 00486 # Changed glt register assignments to bit field assignments 00487 # 00488 # Revision 1.2 2002/12/10 02:42:03 stuvi 00489 # Put the event size plotting outside the tracker strip look 00490 # 00491 # Revision 1.1 2002/12/10 00:59:16 stuvi 00492 # Runcontrol example that uses Hippo. Currently it doesn't work in GUI mode. 00493 # 00494 # Revision 1.4 2002/12/02 17:17:09 claus 00495 # Added provision to allow application to run stand-alone 00496 # 00497 # Revision 1.3 2002/11/28 02:02:04 claus 00498 # Shuffled constructor arguments 00499 # 00500 # Revision 1.2 2002/11/27 23:49:27 claus 00501 # Initialize semaphore with zero count 00502 # 00503 # Revision 1.1 2002/11/27 05:02:48 claus 00504 # Initial version of Run Control 00505 #