/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/Control/BossCommon/BossCommon-01-04-19/share/boss.py

Go to the documentation of this file.
00001 exec env LD_PRELOAD="libGaudiKernel.so libBossServices.so $LD_PRELOAD" python -itx "$0" "$@"
00002 
00003 # File: boss.py
00004 # Author: Wim Lavrijsen (Wim.Lavrijsen@cern.ch)
00005 
00006 # This script allows you to run Boss from python. It is developed against
00007 # GaudiPython v4r0 and python 2.2.1, but will likely work for older versions
00008 # of GaudiPython and python versions after 2.0.
00009 # A jobOptions.txt file is allowed for backwards compatibility. Debugging is
00010 # supported with the '-d' option.
00011 
00012 ### load python modules that are used in this script
00013 import sys, os, re
00014 
00015 ### unhack the hack, such that it doesn't interfere with spawning of processes
00016 if os.environ.has_key( 'LD_PRELOAD' ):
00017    import string
00018    ldpreload = string.strip( string.replace(
00019       os.environ[ 'LD_PRELOAD' ], 'libGaudiKernel.so libBossServices.so', '' ) )
00020 
00021    if len(ldpreload) == 0:
00022       del os.environ[ 'LD_PRELOAD' ]
00023    else:
00024       os.environ[ 'LD_PRELOAD' ] = ldpreload
00025 
00026 ### readline support
00027 import rlcompleter, readline
00028 
00029 # workaround for gcc dynamic loading change, unless GaudiKernel is preloaded
00030 #if sys.platform == 'linux2':
00031 #   import commands
00032 #   stat, out = commands.getstatusoutput( 'gcc -dumpversion' )
00033 #   if 3 <= len(out) and out[:3] == '3.2':
00034 #      sys.setdlopenflags( 0x100 | 0x2 )      # RTLD_GLOBRAL | RTLD_NOW
00035 #   del commands
00036 
00037 ### feedback to the user that she's running boss
00038 sys.ps1 = 'boss> '
00039 
00040 ### messaging functions
00041 def AthMessage( descr ):
00042    print " ==>         : " + descr
00043 
00044 def AthWarning( descr ):
00045    print " ==> WARNING : " + descr
00046 
00047 def AthError( descr ):
00048    print " ==> ERROR   : " + descr + '!'
00049    sys.exit( -1 )                            # <== Note exit function!
00050 
00051 def Usage( prog ):
00052    print "usage: %s [-d [<debugger>]] [script1.py [script2.py [...]]]" % prog
00053    sys.exit( -1 )                            # <== Note exit function!
00054 
00055 ### file inclusion
00056 try:
00057    optionsPath = os.environ[ 'JOBOPTSEARCHPATH' ]
00058 except:
00059    optionsPath = os.curdir
00060 
00061 optionsPath = re.split( ',|' + os.pathsep, optionsPath )
00062 if '' in optionsPath:
00063    optionsPath[ optionsPath.index( '' ) ] = str(os.curdir)
00064 
00065 def where( filename, pathlist = [] ):
00066  # special case for those filenames that already contain a path
00067    if os.path.dirname( filename ):
00068       if os.access( filename, os.R_OK ):
00069          return filename
00070 
00071  # test the file name in all possible paths until first found
00072    for path in pathlist:
00073       f = os.path.join( path, filename )
00074       if os.access( f, os.R_OK ):
00075          return f
00076 
00077  # no such accessible file avalailable
00078    return ''
00079 
00080 def printFile( fn ):
00081    AthMessage( 'begin listing of "%s"' % fn )
00082 
00083    f = open( fn, 'r' )
00084    for line in f.readlines():
00085       print line,
00086    f.close()
00087 
00088    AthMessage( 'end listing of "%s"' % fn )
00089 
00090 def include( fn ):
00091    name = where( os.path.expanduser( os.path.expandvars( fn ) ), optionsPath )
00092    if not os.path.exists( name ):
00093       name = where( os.path.basename( fn ), optionsPath )
00094       if os.path.exists( name ):
00095          AthWarning( 'using %s instead of %s' % (name,fn) )
00096       else:
00097          AthError( 'include file %s can not be found' % fn )   # exits
00098 
00099    printFile( name )
00100    execfile( name, globals() )
00101 
00102 ### check version
00103 if sys.hexversion != 0x020001F0 and not ( 0x20200F0 <= sys.hexversion
00104       and sys.hexversion <= 0x020203F0 ):
00105    AthWarning( "script only tested with python 2.0.1, 2.2.[0123]" )
00106 
00107 ### setup variable name completion
00108 readline.parse_and_bind( 'tab: complete' )
00109 readline.parse_and_bind( 'set show-all-if-ambiguous On' )
00110 
00111 ### use default 'jobOptions.txt' file for backwards compatibility
00112 argc = len( sys.argv )
00113 jobOptions = ""
00114 if argc == 1 or ( ( argc == 2 or argc == 3 ) and sys.argv[1] == '-d' ):
00115    if os.path.exists( "jobOptions.txt" ): jobOptions = "jobOptions.txt"
00116 
00117 ### get user options and store names of any additional scripts
00118 doDebug = ( '', 0 )              # no debugging by default
00119 scripts = []
00120 for arg in sys.argv[1:]:
00121    if arg == '-d':
00122       doDebug = ( 'gdb', 1 )     # select debugging, default gdb
00123       continue
00124    elif arg[0] == '-':           # unknown option, probably request for help
00125       Usage( sys.argv[0] )
00126    elif not ( doDebug[1] or os.path.exists( arg ) ): # expect files or debugger option
00127       AthError( "file '%s' does not exist" % arg )
00128 
00129    if arg[-3:] == ".py":         # select python scripts
00130       scripts.append( arg )
00131    elif arg[-4:] == ".txt":      # allow 1 jobOptions.txt file
00132       if jobOptions != "":
00133          AthWarning( "ignoring file '%s'" % arg )
00134       else:
00135          jobOptions = arg
00136    else: # what's the user trying to do?!
00137       if doDebug[1]: # perhaps user specified a debugger?
00138          doDebug = ( arg, 0 )    # select arg and (temporarily) deselect debugging
00139       else: # well, that seems unintelligible
00140          Usage( sys.argv[0] )
00141 
00142 ### if a (seemingly valid) debugger was specified, reselect debugging
00143 if len( doDebug[0] ):
00144    doDebug = ( doDebug[0], 1 )
00145 
00146 ### debugging helper, hook onto interpreter (ok for gdb/Linux and dbx/Solaris)
00147 def __hookDebugger( prog ):
00148    if len( prog ):
00149       pid = os.spawnvp( os.P_NOWAIT, prog, [ prog, 'python', str( os.getpid() ) ] )
00150     # give debugger some time to attach to the python process
00151       import time
00152       time.sleep( 0.500 )
00153 
00154 ### get Gaudi extension classes
00155 from gaudimodule import *
00156 gaudimodule = sys.modules[ 'gaudimodule' ]
00157 del Algorithm, Service
00158 
00159 ### event selector constants
00160 NO_EVSEL    = -99
00161 MONTECARLO  = 0
00162 ZEBRA       = 1
00163 
00164 ### modify the behaviour of the application manager
00165 class AthAppMgr( AppMgr ):
00166  ## add an initialization guard
00167    def __init__( self ):
00168       AppMgr.__init__( self )
00169       self.__dict__[ "isInitialized" ] = 0
00170 
00171  ## helper for loading the proper libraries for each event selector
00172    def _selectEventSelector( self, evsel ):
00173       if evsel == MONTECARLO:
00174          self.Dlls   += [ "McEventSelector" ]
00175          self.ExtSvc += [ "McCnvSvc", "McEventSelector/EventSelector" ]
00176          self.EvtSel  = "Mc"
00177 
00178       elif evsel == ZEBRA:
00179          self.Dlls   += [ "DetDescrCnvSvc", "ZebraTDRCnv", "HbookCnv" ]
00180          self.Dlls   += [ "IdDictDetDescrCnv" ] # needed by DetDescrCnvSvc
00181 
00182          self.ExtSvc += [ "DetDescrCnvSvc" ]    # included _before_ event selector
00183          self.ExtSvc += [ "ZebraTDRCnvSvc", "ZebraTDREventSelector/EventSelector" ]
00184          self.EvtSel = "ZebraTDR"
00185 
00186       elif evsel == NO_EVSEL:
00187          pass                      # quiet
00188 
00189       else:
00190          AthMessage( "unknown event selector, nothing selected" )
00191 
00192  ## helper to load the services during setup
00193    def _setupServices( self, evsel ):
00194       global DetectorStore, EventPersistencySvc, EventSelector, MessageSvc, StoreGate
00195 
00196       DetectorStore            = Service( "DetectorStore" )
00197       EventPersistencySvc      = Service( "EventPersistencySvc" )
00198       EventSelector            = Service( "EventSelector" )
00199       MessageSvc               = Service( "MessageSvc" )
00200       StoreGate                = Service( "StoreGateSvc" )
00201 
00202       if evsel == MONTECARLO:
00203          global McCnvSvc
00204          McCnvSvc                 = Service( "McCnvSvc" )
00205          EventPersistencySvc.CnvServices = [ "McCnvSvc" ]
00206 
00207       elif evsel == ZEBRA:
00208          global DetDescrCnvSvc, ZebraTDRCnvSvc
00209          DetDescrCnvSvc           = Service( "DetDescrCnvSvc" )
00210          ZebraTDRCnvSvc           = Service( "ZebraTDRCnvSvc" )
00211          EventPersistencySvc.CnvServices = [ "DetDescrCnvSvc", "ZebraTDRCnvSvc" ]
00212 
00213          DetDescrCnvSvc.IdDictName = "BES_IDS.xml"
00214          DetDescrCnvSvc.CompactIDsOnly = TRUE
00215 
00216       elif evsel == NO_EVSEL:
00217          pass                      # quiet
00218 
00219       else:
00220          AthMessage( "unknown event selector, none instantiated" )
00221 
00222       MessageSvc.OutputLevel             = INFO
00223 
00224   ## user  call
00225    def setup( self, name = NO_EVSEL ):
00226     # get the proper event selector
00227       self._selectEventSelector( name )
00228 
00229     # actual loading of all specified dlls and services
00230       AthMessage( "configuring ... " )
00231       self.config()
00232 
00233     # add auditor function to the AuditorSvc
00234       audSvc = AuditorSvc()
00235       audSvc.__dict__[ 'auditor' ] = theApp.service
00236 
00237     # create views of services for the user
00238       self._setupServices( name )
00239 
00240  ## redefine run to force initialisation
00241    def run( self, nEvt = -1 ):
00242     # get current state (TODO: get state from Boss/C++ side)
00243       init = self.__dict__[ "isInitialized" ]
00244 
00245     # initialize if needed
00246       if not init:
00247          AthMessage( "initializing ... " )
00248          status = self.initialize()
00249          if not status.isSuccess():
00250             raise RuntimeError, "application manager initialization failed"
00251          self.__dict__[ "isInitialized" ] = 1
00252 
00253     # determine number of events
00254       if nEvt <= 0:
00255          if 0 < self.EvtMax:
00256             nEvt = self.EvtMax
00257          else:
00258             nEvt = 1
00259 
00260     # actual run
00261       AppMgr.execute( self, nEvt )
00262 
00263 ### get a view of the application manager and start in a non-initialised state
00264 theApp = AthAppMgr()
00265 
00266 ### rebind globals to call directly into the application manager view
00267 def _cachedLookup( name, cache, func ):
00268    try:
00269       res = cache[ name ]
00270    except KeyError:
00271       res = func( name )
00272       cache[ name ] = res
00273    return res
00274 
00275 _algorithms, _services = {}, {}
00276 Algorithm  = lambda name : _cachedLookup( name, _algorithms, theApp.algorithm )
00277 Service    = lambda name : _cachedLookup( name, _services,   theApp.service   )
00278 AuditorSvc = lambda : _cachedLookup( 'AuditorSvc', _services, theApp.service )
00279 
00280 ### hacks to allow assignment to non-existent lists ...
00281 class _AlgSvcMemberProxy:
00282    def __init__( self, name, owner ):
00283       self.__dict__[ 'name' ] = name
00284       self.__dict__[ 'owner' ] = owner
00285       self.owner.__dict__[ self.name ] = self
00286 
00287    def __iadd__( self, what ):
00288       del self.owner.__dict__[ self.name ]                            # Python
00289       self.owner.__class__.__setattr__( self.owner, self.name, what ) # C++
00290       return getattr( self.owner, self.name )
00291 
00292    def __setattr__( self, attr, value ):
00293       fullname = self.owner.name() + '.' + self.name
00294       if type( self.owner ) == type( gaudimodule.Algorithm ):
00295          newself = Algorithm( fullname )
00296       else:
00297          newself = Service( fullname )
00298       self.owner.__dict__[ self.name ] = newself
00299       setattr( newself, attr, value )
00300 
00301 class _AlgSvcRedirect:
00302    def __init__( self, func ):
00303       self.func = func
00304 
00305    def __call__( self, what, name ):
00306       try:
00307          return self.func( what, name )
00308       except ( TypeError, RuntimeError ):
00309          return _AlgSvcMemberProxy( name, what )
00310 
00311 gaudimodule.Algorithm.__getattr__ = _AlgSvcRedirect( gaudimodule.Algorithm.__getattr__ )
00312 gaudimodule.Service.__getattr__   = _AlgSvcRedirect( gaudimodule.Service.__getattr__ )
00313 
00314 
00315 ### take care of job options legacy
00316 theApp.JobOptionsPath = jobOptions
00317 if jobOptions != "":
00318    AthWarning( "using job options file '%s'" % jobOptions )
00319    theApp.JobOptionsType    = "FILE"
00320 else:
00321    theApp.JobOptionsType    = "NONE"
00322 
00323 ### specify the required dlls and start the required services
00324 
00325 # BossServices is not needed if it is preloaded, which is currently the case
00326 #theApp.Dlls    = [ "BossServices" ]
00327 
00328 theApp.ExtSvc  = [ "IncidentSvc/IncidentSvc",
00329                    "EvtPersistencySvc/EventPersistencySvc",
00330                    "HistogramSvc/HistogramDataSvc",
00331                    "NTupleSvc/NTupleSvc",
00332                    "ToolSvc/ToolSvc",
00333                    "AuditorSvc/AuditorSvc",
00334                    "RndmGenSvc/RndmGenSvc",
00335                    "ChronoStatSvc/ChronoStatSvc" ]
00336 
00337 ### specify StoreGate dlls and services
00338 try:
00339    sgfile = os.path.join( os.environ[ 'STOREGATEROOT' ], 'share', 'StoreGate.py' )
00340    include( sgfile )
00341 except (KeyError, IOError, OSError):
00342    AthWarning( "StoreGate.py not found, selecting defaults" )
00343    theApp.Dlls   += [ 'StoreGate', 'CLIDSvc' ]
00344    theApp.ExtSvc += [ 'ClassIDSvc' ]
00345    theApp.ExtSvc += [ 'StoreGateSvc', 'StoreGateSvc/DetectorStore', 'StoreGateSvc/ConditionsStore' ]
00346    theApp.ExtSvc += [ 'ActiveStoreSvc' ]
00347 
00348 ### Bes specific event loop and output stream
00349 theApp.EventLoop         = "BossEventLoopMgr"
00350 theApp.OutStreamType     = "BossOutputStream"
00351 
00352 ### some useful constants
00353 ALL     = 0
00354 VERBOSE = 1
00355 DEBUG   = 2
00356 INFO    = 3
00357 WARNING = 4
00358 ERROR   = 5
00359 FATAL   = 6
00360 
00361 TRUE    = 1
00362 FALSE   = 0
00363 
00364 ### from this point, user code with algorithms can take over
00365 if len( scripts ):
00366  # simplistic sanity check
00367    doesSetup = 0
00368    scrfile = open( scripts[ 0 ], 'r' )
00369    for line in scrfile.readlines():
00370       pos = line.find( "theApp.setup" )
00371       if 0 <= pos and line[:pos].find( '#' ) < 0:
00372          doesSetup = 1
00373          break
00374    del scrfile
00375 
00376    if not doesSetup:
00377       AthWarning( "missing call to 'theApp.setup()' in first script" )
00378 
00379  # ready for execution, set the exit handler
00380    import atexit
00381    atexit.register( theApp.exit )
00382 
00383  # process all user provided scripts
00384    for script in scripts:
00385       include( script )
00386 
00387  # start debugging after all user provided scripts
00388    if doDebug[1]:
00389       __hookDebugger( doDebug[0] )
00390 
00391 elif jobOptions != "":   # run in batch mode
00392  # actual run, note that this is fully batch if we're not debugging
00393    theApp.config()
00394    theApp.initialize()
00395 
00396  # all symbols have been loaded, but nothing has been run, good time for debug
00397    if doDebug[1]:
00398       __hookDebugger( doDebug[0] )
00399 
00400  # resume batch mode
00401    theApp.run( theApp.EvtMax )
00402    theApp.exit()
00403 
00404 # still here? Ok, go interactive
00405 AthMessage( 'entered interactive mode' )

Generated on Tue Nov 29 22:57:58 2016 for BOSS_7.0.2 by  doxygen 1.4.7