The first Bender algorithms

Prequisites

  • One needs to understand the structure of Bender module : run, configure functions and the __main__ clause
  • One needs to know the structure and the content of configure function

Learning objectives

  • Understand Bender algorithms
    • How to code them?
    • How to embed them into the application?

Hello, world!

Traditionally for tutorials, the first algorithm prints Hello, world. The Bender algorithm inherits from the class Algo, imported from Bender.Main module. This python base is indeed a C++-class, that inherits from LoKi::Algo class, that in turn inherits from DaVinciTupleAlgorithm. The simplest algorithm is rather trivial:

from Bender.Main import Algo, SUCCESS 
class HelloWorld(Algo):
    """The most trivial algorithm to print 'Hello,world!'"""
    def analyse( self ) :   ## IMPORTANT! 
        """The main 'analysis' method"""        
        print       'Hello, world! (using native Python)'
        self.Print( 'Hello, World! (using Gaudi)')
        return SUCCESS      ## IMPORTANT!!!

Important note:

  • one must implement the method analyse that gets no argument and returns StatusCode

Optionally one can (re)implement other important methods, like __init__, initialize , finalize, etc... In particular initialize could be used to locate some tools and or pre-define some useful code fragments, e.g. some expensive or non-trivial LoKi-functors.

Where to put the algorithm code?Click to expand

How to embed the algorithm into the application ?

There are two approaches brute-force, that works nicely with such primitive code as HelloWorld algorithm above and the intelligent/recommended approach, that smoothly insert the algorithm into the overall flow of algorithms, provided by DaVinci

Brute-force

One can instantiate the algorithm in configure method after the instance of application manager is created, and add the algorithm, into the list of top-level algorithms, known to Gaudi:

gaudi = appMgr() 
alg   = HelloWorld('Hello')
gaudi.addAlgorithm( alg )

For this particular simple case one can also just replace the list of top-level Gaudi algorithms with a single HelloWorld algorithm:

gaudi = appMgr() 
alg   = HelloWorld('Hello')
gaudi.setAlgorithms( [ alg ] )

More on an optional _dynamic configuration_Click to expand

This approach is very easy and rather intuitive, but is not so easy to insert the algorithm into existing non-trivial flow of algorithms without a danger to destroy the flow. In this way one destroys various standard actions, like (pre)filtering, luminosity calculation etc., therefore it could not be recommended for the real physics analyses, but it could be used for some simple special cases.

Intelligent approach

For intelligent approach one uses Selection wrapper for Bender algorithm, BenderSelection. This wrapper behaves as any other selection-objects, and it lives in static configuration part of configure function:

from PhysConf.Selections import AutomaticData,  PrintSelection
particles = AutomaticData  ( 'Phys/SelPsi2KForPsiX/Particles' ) 
particle  = PrintSelection ( particles )  

## configuration object for Bender algorithm:
#                              name   , input selections 
hello = BenderSelection ( 'Hello' , inputs = [ particle ]  )  
dv.UserAlgorithms.append ( hello )

As the next step in dynamic configuration part of configure function one instantiates the algorithm taking all the configuration from the selection-object:

gaudi = appMgr() 
alg   = HelloWorld( hello )

To complete the module one (as usual) need to combine in the file

  1. implementation of HelloWorld algorithm
  2. configure function with proper static and dynamic configurations
  3. __main__ clause
  4. (run function is imported from Bender.Main module)

The complete module can be accessed here

Get data, fill histos & n-tuples

Well, now your Bender algorithm knows how to print Hello,world!. Note that it also gets some data: in the previous example we fed it with particles-selection. Now try to get this data inside the algorithm and make first simple manipulations with data.

select method

The method select is a heart of Bender algorithm. It allows to select/filter the particles that satisfies some criteria from the input particles. The basic usage is:

myB = self.select ( 'myB' , ('B0' ==  ABSID ) | ('B0' ==  ABSID ) )

The method returns collection filtered particles. The first argument is the tag, that will be associated with selected particles, the second argument is the selection criteria. The tag must be unique, and the selection criteria could be in a form of

  • LoKi predicate: LoKi-functor that get the particle as argument and return the boolean value
  • decay descriptor , e.g. 'Beauty --> J/psi(1S) K+ K-'. Some components of the decay descriptor can be marked, and in this case, only the marked particles will be selected:
    myB = self.select ( 'beauty' , 'Beauty --> J/psi(1S)  K+  K-')   ## get the heads of the decay
    myK = self.select ( 'kaons'  , 'Beauty --> J/psi(1S) ^K+ ^K-')   ## get only kaons
    

As soon as one gets some good, filtered particles there are many possible actions

  • print it!
    myB = self.select ( 'myB' , ('B0' ==  ABSID ) | ('B0' ==  ABSID ) )
    print myB
    
  • loop
    myB = self.select ( 'myB' , ('B0' ==  ABSID ) | ('B0' ==  ABSID ) )
    for b in myB : 
     print 'My Particle:', p 
     print 'some quantities: ', M(p) , PT(p) , P(p)
    
  • fill histograms
    myB = self.select ( 'myB' , ('B0' ==  ABSID ) | ('B0' ==  ABSID ) )
    for b in myB : 
     #          what        histo-ID    low-edge  high-edge  #bins 
     self.plot( PT (p)/GeV , 'pt(B)'  , 0        , 20       ,  50  ) 
     self.plot( M  (p)/GeV , 'm(B)'   , 5.2      , 5.4      , 100  ) 
     self.plot( M1 (p)/GeV , 'm(psi)' , 3.0      , 3.2      , 100  )
     self.plot( M23(p)/GeV , 'm(KK)'  , 1.0      , 1.050    ,  50  )
    
  • fill n-tuple:
    myB = self.select ( 'myB' , ('B0' ==  ABSID ) | ('B0' ==  ABSID ) )
    t = self.nTuple('TupleName') 
    for b in myB : 
     t.column_float ( 'pt'    , PT (p)/GeV) 
     t.column_float ( 'm'     , M  (p)/GeV) 
     t.column_float ( 'm_psi' , M1 (p)/GeV) 
     t.column_float ( 'm_kk'  , M23(p)/GeV) 
     t.write()
    

    For n-tuples...Click to expand

Challenge

Add select statements, histos and tuples to your HelloWorld algorithm, created earlier, and run it.

Solution

The complete module is accesible here

Keypoints

Wth these two examples, you should aready be able to

  • code Bender algorithms and insetr them into overall algorithm flow
  • loop over data, fill historgrams and n-tuples

results matching ""

    No results matching ""