00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2005 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 test the TKR hit filter" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = "1/28/2005" 00014 __version__ = "$Revision: 1.4 $" 00015 __credits__ = "SLAC" 00016 00017 import LATTE.copyright_SLAC 00018 00019 import threading 00020 import logging as log 00021 00022 from LATTE.runcontrol.rcTransitions import rcTransitions 00023 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00024 import time 00025 00026 from support.SimpleGasuExample import * 00027 from support.MiniGLTExample import * 00028 00029 # This class puts up a GUI for inputting a value of some sort. It is used by 00030 # the userApplication example to get the number of self triggers to take. 00031 class userArgument(ArgumentImpl): 00032 "GUI for getting the user to input some sort of value." 00033 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00034 ArgumentImpl.__init__(self, parent, name, modal, fl) 00035 self.__value = 0 00036 self.setCaption("Enter value:") 00037 00038 def CancelButtonClicked(self): 00039 self.__value = None 00040 self.close() 00041 00042 00043 class userArgText(object): 00044 "Text user interface for getting the user to input some sort of value" 00045 def __init__(self): 00046 pass 00047 00048 def getValue(self, caption, value = None): 00049 if value is None: 00050 ans = raw_input("%s: " % (caption)) 00051 if ans == '': return None 00052 return int(ans) 00053 else: 00054 ans = raw_input("%s[%s]: " % (caption, str(value))) 00055 if ans == '': return value 00056 return int(ans) 00057 00058 # Example application implementation. 00059 # Note that the name of the class must be userApplication. 00060 # Look at rcTransitions for names of other transition methods that can be used. 00061 class userApplication(rcTransitions): 00062 "Implmentation class for a user application" 00063 def __init__(self, rc, userId, debug): 00064 rcTransitions.__init__(self, rc, userId, debug) 00065 log.debug("userApplication.__init__()") 00066 self.__cmdSynchSem = threading.Semaphore(0) 00067 self.__cnt = 1 00068 self.__lowThresh = 10 00069 self.__highThresh = 100 00070 self.__towerMask = 0x0000ffff 00071 self.__prescale = 0xffffffffL 00072 00073 def getName(self): 00074 return __name__ 00075 00076 def setup(self): 00077 if self.rc is None: 00078 self.__arg = userArgText() 00079 else: 00080 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00081 00082 # Get a TEM instance 00083 if self.lat.TEMcnt() == 1: 00084 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00085 elif self.lat.TEMcnt() > 1: 00086 tem = self.lat.TEM.all() 00087 else: 00088 log.fatal("No TEM(s) found in the schema") 00089 return -1 00090 00091 # Move to schema configuration 00092 # # reset the TEM since we are going to modify DATA_MASKS 00093 # tem.CMD_RESET = 1 00094 00095 # # 00096 # # Configure TEM 00097 00098 # # config TEM TKR calstrobe delay for ~ 5usec 00099 # tem.TKR_TRGSEQ = 0x3C 00100 00101 # # enable TKR, no diag # 0x1F00 for diag 00102 # # make sure we also enable CAL CC 1 since it is required for 00103 # # proper event data taking 00104 # # enable GTCC 2 and 3 00105 # tem.DATA_MASKS = 0x0DF3 00106 # tem.configuration = 0x00010000L # primary 00107 # #tem.CONFIGURATION = 0x03010000L # redundant 00108 00109 # ccc = tem.allCCC() 00110 # # enable output in our GCCCs 00111 # # broadcast load of GCCC_REG_CONFIGURATION 00112 # ccc.CONFIGURATION = 0x80000000L 00113 00114 # # disable all GCRCs in all GCCCs via broadcast 00115 # ccc.LAYER_MASK_0 = 0xFFFFFFFFL 00116 # ccc.LAYER_MASK_1 = 0xFFFFFFFFL 00117 00118 tcc = tem.allTCC() 00119 00120 # broadcast load of GTCC_REG_CONFIGURATION 00121 # enable controller output and set cable length to 1 00122 # 0xC0000000 is for one layer 00123 # 0x80000000 is for two layers 00124 tcc.CONFIGURATION = 0xC0000000L 00125 x_tcc = tem.downTCC(0) 00126 # enable all masks 00127 tcc.INPUT_MASK = 0x0 00128 00129 # set maximum event timeout 00130 tcc.EVENT_TIMEOUTS = 0x0 00131 00132 # 00133 # Configure GTRCs 00134 # 00135 00136 # our board is connected CC = 2, RC = 0 and CC = 3, RC = 0 00137 # reset GTRC # required before all triggers 00138 00139 trc = tcc.allTRC() 00140 00141 trc.CMD_RESET = 1 00142 00143 # number of GTFE to readout left 00144 nGTFEsLeft = 7 00145 nGTFEsRight = 0 00146 00147 # max hits per GTRC # 31 max 00148 maxHits = 31 00149 00150 enMask = 0x6 00151 00152 dLO = (enMask << 28) | ((nGTFEsRight << 7)& 0xF80) | (maxHits & 0x7F); 00153 #print "dLO=", dLO, hex(dLO) 00154 00155 # cable controller 2, readout controller 0 00156 tcc = tem.downTCC(2) 00157 trc = tcc.downTRC(1) 00158 00159 trc.CSR = dLO 00160 00161 dLO = (enMask << 28) | ((nGTFEsLeft << 7)& 0xF80) | (maxHits & 0x7F); 00162 #print "dLO=", dLO, hex(dLO) 00163 00164 # cable controller 3, readout controller 0 00165 tcc = tem.downTCC(3) 00166 trc = tcc.downTRC(1) 00167 00168 trc.CSR = dLO 00169 00170 # 00171 # Configure GTFEs 00172 # 00173 00174 tfe = trc.allTFE() 00175 tfe.TRIG_MASK = 0x0 00176 tfe.DATA_MASK = 0x0 00177 tfe.CALIB_MASK = 0x0 00178 tfe.DAC = 0x00001902 00179 # configure front ends # all listen to left 00180 tfe.MODE = 0 00181 #tfe = trc.downTFE(0) 00182 00183 # configure default DACs for threshold and calibration 00184 # Calibration DAC Range and Resolution 00185 # Low Range (B6=0): DAC output voltage in mV = 1.57 + 1.53*DAC_Value 00186 # High Range (B6=1): DAC output voltage in mV = 15.0 + 14.6*DAC_Value 00187 # Discriminator Threshold DAC Range and Resolution 00188 # Low Range (B6=0): DAC output voltage in mV = 4.5 + 4.5*DAC_Value 00189 # High Range (B6=1): DAC output voltage in mV = 12.9 + 12.9*DAC_Value 00190 00191 00192 # calRng = 1 00193 # thrRng = 0 00194 # calDAC = 60 00195 # thrDAC = 10 00196 00197 tfe.DAC = 0x00001952 # based on the above Rng and DAC values 00198 00199 # enable GTFE for data taking # all channels 00200 tfe.TRIG_MASK = 0xffffffffffffffff 00201 tfe.DATA_MASK = 0xffffffffffffffff 00202 00203 # Cal strobe channels 4 and 48 only 00204 tfe.CALIB_MASK = 0x0001000000000010 00205 00206 #~ #Mask of the following Registers 00207 #~ tfe = trc.downTFE(13) 00208 #~ tfe.DATA_MASK = 0x0L 00209 #~ tfe.CALIB_MASK = 0x0L 00210 #~ tfe.TRIG_MASK = 0x0L 00211 00212 #~ tfe = trc.downTFE(14) 00213 #~ tfe.DATA_MASK = 0x0L 00214 #~ tfe.CALIB_MASK = 0x0L 00215 #~ tfe.TRIG_MASK = 0x0L 00216 00217 #~ tfe = trc.downTFE(19) 00218 #~ #tfe.DATA_MASK = 0x0L 00219 #~ tfe.CALIB_MASK = 0x0L 00220 #~ tfe.TRIG_MASK = 0x0L 00221 00222 #~ tfe = trc.downTFE(20) 00223 #~ #tfe.DATA_MASK = 0x0L 00224 #~ tfe.CALIB_MASK = 0x0L 00225 #~ tfe.TRIG_MASK = 0x0L 00226 00227 00228 00229 # Two choices for the trigger, GEM and MiniGLT 00230 if self.lat.existsGEM(): 00231 self.trigger( SimpleGasuExample() ) 00232 else: 00233 self.trigger( MiniGLTExample() ) 00234 00235 00236 # A state transition can be rejected by not returning None 00237 return None 00238 00239 def startRun(self): 00240 caption = "Enter number of triggers to take" 00241 if self.rc is None: 00242 cnt = self.__arg.getValue(caption, self.__cnt) 00243 else: 00244 cnt = self.rc.execGUImethod(self.__arg.getValue, caption, self.__cnt) 00245 00246 # The user pressed 'Cancel' 00247 if cnt is None: return -1 00248 self.__cnt = cnt 00249 00250 caption = "Enter the tracker hit low threshold" 00251 if self.rc is None: 00252 lowThresh = self.__arg.getValue(caption, self.__lowThresh) 00253 else: 00254 lowThresh = self.rc.execGUImethod(self.__arg.getValue, caption, self.__lowThresh) 00255 if lowThresh is None: return -1 # The user pressed 'Cancel' 00256 self.__lowThresh = lowThresh 00257 00258 caption = "Enter the tracker hit high threshold" 00259 if self.rc is None: 00260 highThresh = self.__arg.getValue(caption, self.__highThresh) 00261 else: 00262 highThresh = self.rc.execGUImethod(self.__arg.getValue, caption, self.__highThresh) 00263 if highThresh is None: return -1 # The user pressed 'Cancel' 00264 self.__highThresh = highThresh 00265 00266 caption = "Enter the tower mask" 00267 if self.rc is None: 00268 towerMask = self.__arg.getValue(caption, self.__towerMask) 00269 else: 00270 towerMask = self.rc.execGUImethod(self.__arg.getValue, caption, self.__towerMask) 00271 if towerMask is None: return -1 # The user pressed 'Cancel' 00272 self.__towerMask = towerMask 00273 00274 caption = "Enter the prescale value" 00275 if self.rc is None: 00276 prescale = self.__arg.getValue(caption, self.__prescale) 00277 else: 00278 prescale = self.rc.execGUImethod(self.__arg.getValue, caption, self.__prescale) 00279 if prescale is None: return -1 # The user pressed 'Cancel' 00280 self.__prescale = prescale 00281 00282 self.rc.common().getOCS().evtHandlerSetVerbosity(1) 00283 self.rc.common().getOCS().evtHandlerFilterTkrHits(lowThresh, towerMask, highThresh, prescale) 00284 00285 # Spawn a thread to synchronize commands with events 00286 # This must happen after triggers are enabled 00287 self.__cmdSynchQuit = False 00288 00289 # A state transition can be rejected by not returning None 00290 return None 00291 00292 def stopRun(self): 00293 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00294 self.__cmdSynchQuit = True 00295 00296 # The STOP_RUN transition can not be rejected 00297 00298 def resume(self): 00299 # Issue self trigger to make up for the one that was lost during PAUSE 00300 self.trigger().solicit() 00301 00302 return None 00303 00304 def stop(self): 00305 return self.stopRun() 00306 00307 def teardown(self): 00308 # Allow the C++ object to be deleted 00309 if self.rc is not None and self.__arg is not None: 00310 self.__arg.deleteLater() 00311 00312 def process(self, (status, buffer)): 00313 "Method called back for each data event taken" 00314 00315 evtCli = self.evtCli 00316 00317 if status != 0: 00318 if evtCli.isGGLTStatus(): 00319 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00320 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00321 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00322 return 00323 try: 00324 # In the future this event may contain additional data 00325 if evtCli.isSweepEvent(): return 00326 except: 00327 # Event summary word inaccessible, handle the bad event here 00328 log.exception("") 00329 return 00330 00331 hits = 0 00332 for contributor in range(16): # TEM ids 00333 if evtCli.setCurrentContribution(contributor) != -1: 00334 #evtCli.evDumpSummary() 00335 evtCli.evDumpTKR() 00336 #evtCli.evDumpTEM_Error() 00337 #evtCli.evDumpDiagnostic() 00338 00339 hits += len(evtCli.evt.TKRstrips) 00340 #for strip in evtCli.evt.TKRstrips: 00341 # print strip.ui 00342 print "TEM %d TKRSTRIPS: %d" % (contributor, len(evtCli.evt.TKRstrips)) 00343 else: 00344 if False: 00345 print "*******************************************" 00346 print "* NO TEM %2d CONTRIBUTION PRESENT *" % (contributor) 00347 print "*******************************************" 00348 00349 print "Total TKR strip hits =", hits 00350 00351 #def __commandSynch(self, count): 00352 def commandSynch(self): 00353 "Method called by the command synchronization task" 00354 import time 00355 trigger = self.trigger() 00356 00357 t0 = time.time() 00358 00359 # Compensate for the extra CMD_SELF_TRIGGER below 00360 cnt = 1 00361 count = self.__cnt 00362 00363 # Wait for START_RUN to enable triggers 00364 trigger.waitForMaskEnable() 00365 00366 trigger.solicit() # Issue an internal trigger 00367 00368 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00369 00370 while cnt < count and not self.__cmdSynchQuit: 00371 cnt += 1 00372 trigger.solicit() # Issue an internal trigger 00373 time.sleep(.1) 00374 00375 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00376 # When we get here the triggers should still be enabled. 00377 # If the glt.MASK needs to be set through any other means 00378 # then it needs to be restored to its SETUP value here. 00379 00380 if t1 is None: 00381 t1 = t0 00382 if t2 is None: 00383 t2 = time.time() 00384 dT = t2 - t1 00385 if dT == 0.0: dT = 0.000001 00386 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00387 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00388 00389 # Get out of waiting when in suite or standalone mode 00390 self.sync() 00391 00392 # execute the GUI functions for stopRun, just in case 00393 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00394 if self.rc is not None: 00395 self.rc.doStop() 00396 00397 def wait(self): 00398 self.__cmdSynchSem.acquire() 00399 00400 def sync(self): 00401 if __name__ == "__main__" or self.isRunFromSuite(): 00402 self.__cmdSynchSem.release() 00403 00404 00405 00406 # Standalone mode: 00407 if __name__ == "__main__": 00408 from LATTE.runcontrol.RunControlCommon import RunControlCommon 00409 00410 rcCommon = RunControlCommon() 00411 rcCommon.initialize() 00412 rcCommon.setLoggingLevel("INFO") 00413 rcCommon.connect() 00414 ua = userApplication(None, 321, rcCommon) 00415 ua.rcSetup() 00416 ua.rcStartRun() 00417 ua.wait() 00418 ua.rcStopRun() 00419 ua.rcTeardown()