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 returnsStatusCode
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
- implementation of
HelloWorld
algorithm configure
function with proper static and dynamic configurations__main__
clause- (
run
function is imported fromBender.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