TWiki> LHCb Web>LHCbComputing>LoKi>LoKiLUG (revision 2)EditAttachPDF

LoKi User Guide


LoKi is a package for the simple and user-friendly data analysis. LoKi is based on Gaudi architecture. The current functionality of LoKi includes the selection of particles, manipulations with predefined kinematic expressions, loops over combinations of selected particles, creation of composite particles from various combinations of particles, flexible manipulation with various kinematic constrains and access to Monte Carlo truth information.

User Guide


All off-line OO software for simulation, digitization, recontruction, vizualization and analysis, for LHCb collaboration is based on Gaudi framework. All software is written on C++, which is currently the best suited language for large scale OO software projects. It is worth to mention here that for the experts coding in C++ is like a real fun. The language itself and its embedded abilities to provide ready-to-use' nontrivial, brilliant and exiting solution for almost all ordinary, tedious and quite boring problems seems to be very attractive features for persons who has some knowledge and experience with OO programming. Unfortunately C++ requires significant amount of efforts from beginners to obtain some first results of acceptable quality. An essential static nature of the language itself requires the knowledge of compilation and linkage details. In addition quite often in the "typical" code fragments for physical analysis the explicit C++ semantics and syntax hide the "physical" meaning of the line and thus obscure the physical analysis algorithm. Often a simple operation corresponding to one "physics" statement results in an enormous code with complicated and probably non-obvious content:

    ParticleVector::const_iterator im;
    for ( im = vDsK.begin(); im != vDsK.end(); im++ ) {
      if((*im)->particleID().pid() == m_DsPlusID||
      (*im)->particleID().pid() == m_DsMinusID) vDs.push_back(*im);
      else if((*im)->particleID().pid() == m_KPlusID||
      (*im)->particleID().pid() == m_KMinusID) vK.push_back(*im);
        log <<MSG::ERROR<< " some message here "<<endreq;
        return StatusCode::FAILURE;

The usage of comments becomes mandatory for understanding makes the code even longer and again results in additional complexity.

The idea of LoKi package is to provide the users with possibility to write the code, which does not obscure the actual physics content by technical C++ semantic. The idea of user-friendly components for physics analysis were essentially induced by the spirit of following packages:

  • KAL language (Kinematical Analysis Language) by genius Hartwig Albrecht. KAL is an interpreter language written on FORTRAN (It is cool, isn't it?). The user writes script-like ASCII file, which is interpreted and executed by standard KAL executable. The package was very successfully used for physics analysis by ARGUS collaboration.
  • Pattern and GCombiner packages by Thorsten Glebe. These nice, powerful and friendly C++ components are used now for the physics analysis by HERA-B collaboration
  • Some obsolete CLHEP classes, like HepChooser and HepCombiner
  • Loki library by Andrei Alexandrescu. The library from one side is a state-of-art for so called generic meta-programming and compile time programming, and simultaneously from another side it is the excellent cook-book, which contains very interesting, non-trivial and non-obvious recipes for efficient solving of major common tasks and problems.

The attractiveness of specialised, physics-oriented code for physics analysis could be demonstrated e.g. with "typical" code fragment in KAL:

    HYPOTH  E+  MU+  PI+ 5  K+  PROTON
    IDENT PI+     PI+
    IDENT K+      K+
    IDENT E+      E+
    IDENT MU+     MU+
    SELECT K- PI+ 
     IF P > 2 THEN
      SAVEFITM D0 DMASS 0.045 CHI2 16  
    SELECT D0 PI+ 
     PLOT MASS L 2.0 H 2.100 NB 100 TEXT ' Mass of D0 pi+ '

    GO 1000000

This KAL pseudo-code gives an example of self-explanatory code. The physical content of selection of ${\mathrm{D}}^{*+}\rightarrow {\mathrm{D}}^0 \pi^+$, followed by ${\mathrm{D}}^0\rightarrow {\mathrm{K}}^-\pi^0$ decay is clear and unambigously visible between lines. Indeed no comments are needed for understanding the analysis within 2 minutes.

One could argue that it is not possible to get the similar transparency of the physical content of code with native C++. The best answer to this argument could be just an example from T. Glebe's Pattern of ${\mathrm{K}}^0_{\mathrm{S}}\rightarrow \pi^+\pi^-$ reconstruction:

   TrackPattern  piMinus = pi_minus.with ( pt > 0.1 & p > 1 ) ;
   TrackPattern  piPlus  = pi_plus.with  ( pt > 0.1 & p > 1 ) ;
   TwoProngDecay kShort  = K0S.decaysTo  ( PiPlus & PiMinus ) ;
   kShort.with( vz > 0   ) ;
   kShort.with( pt > 0.1 ) ;

This code fragment is not so transparent as specialized KAL pseudo-code but it is easy-to-read, the physical content is clear, and it is just a native C++! I personally tend to consider the above code as an experimental prove of possibility to develop easy-to-use C++ package for physics analysis. Indeed the work has been started soon after I've seen these 5 lines.

Here it is a good moment to jump to the end of the whole story and present some LoKi fragment for illustration:

    select ( "Pi+" , ID =="pi+" && P > 5 * GeV ) ;
    select ( "K-"  , ID =="K-"  && P > 5 * GeV ) ;
    for ( Loop D0 = loop("K- pi+","D0") ; D0 ; ++D0 )
      if ( P( D0 ) > 10 * GeV ){ D0->save("D0"); }
    for ( Loop Dstar = loop( "D0 Pi+" , "D*+" ) ; Dstar ; ++Dstar )
      plot ( M( Dstar ) / GeV , " Mass of D0 pi+ " , 2.0 , 2.1 , 100 );

The physical content of these lines is quite transparent. Again I suppose that it is not obscured with C++ semantics. From these LoKi lines it is obvious that an essential emulation of KAL semantics is performed. Indeed I think that KAL was just state-of-art for physics pseudo-code and is practically impossible to make something better. But of course it is the aspect where I am highly biased.

LoKi follows general Gaudi architecture and indeed it is just a thin layer atop of tools, classes, methods and utilities from developed withing DaVinci project.

Since LoKi is just a thin layer, all DaVinci tools are available in LoKi and could be directly invoked and manipulated. However there is no need in it, since LoKi provides the physicist with significantly simpler, better and more friendly interface.

As a last line of this chapter I'd like to thank Galina Pakhlova, Andrey Tsaregorodtsev and Sergey Barsuk for fruitfull discussions and active help in overall desing of LoKi. It is a pleasure to thank Andrey Golutvin as the first active user of LoKi for constructive feedback. Many people have contributed in a very constructive way into available LoKi functionality and development directions. Within them I would like to thank Victor Coco, Hans Dijkstra, Markus Frank, Jose Angel Hernando Morata, Jeroen van Hunen, Sander Klaus, Patrick Koppenburg, Pere Mato, Juan Palacios, Boleslav Pietrzyk, Gerhard Raven, Thomas Ruf, Hugo Ruiz Perez, Jeroen van Tilburg and Benoit Viaud.

It is a pleasure to thank the leaders of ITEP/Moscow, CERN-LBD, LAPP/Annecy and Syracuse University teams for the kind support.

LoKi ingredients

Typical analysis algorithm consists of quite complex combination of the following elementary actions:

  • selection/filtering with the criteria based on particle(s) kinematics, identification and topological properties, e.g. particle momenta, transverse momenta, confidence levels, impact parameters etc.
  • looping over the various combinations of selected particles and applying other criteria based on kinematic properties of the whole combination or any sub-combinations or some topology information (e.g. vertexing), including mass and/or vertex constrain fits.
  • saving of interesting combinations as "particles" which acquire all kinematic properties and could be further treated in the standard way.
  • for evaluation of efficiencies and resolutions the access for Monte Carlo truth information is needed.
  • also required is the filling of histograms and N-tuples.

LoKi has been designed to attack all these five major actions.


Selection of Particles

LoKi allows to select/filter a subset of reconstructed particles (of C++ type LHCb::Particle) which fulfills the chosen criteria, based on their kinematic, identification and topological properties and to refer later to this selected subset with the defined tag:

    select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV ) ;

Here from all particles, loaded by DaVinci, the subset of particles identified as charged kaons (abs(ID)==321) with transverse momentum greater than 100 MeV/c (PT>100*MeV) is selected. These particles are copied into internal local LoKi storage and could be accessed later using the symbolic name "AllKaons".

In this example ID and PT are predefined LoKi variables or functions (indeed they are function objects, or functors in C++ terminology) which allow to extract the identifier and the transverse momentum for the given particle. Cuts or predicates or selection criteria are constructed with the comparison operations '<', '<=', '==', '!=', '>=', '>' from variables. The arbitrary combinations of cuts with the boolean operations '&&' or '||' are allowed to be used as selection criteria.

LoKi defines many frequently used variables and set of the regular mathematical operation on them '+', '-', '*', '/' and all elementary functions, like sin, cos, log, atan, atan2, pow etc, which could be used for construction of variables of the arbitrary complexity. Cuts and variables are discussed in detail in subsequent chapters

Indeed the function select has a return value of type Range, which is essentially the light-weight container of selected particles. The returned value could be used for immediate access to the selected particles and in turn could be used for further sub-selections. The following example illustrates the idea: the selected sample of kaons is subdivided into samples of positive and negative kaons:

    Range kaons =  select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV );
    select( "kaon+" , kaons , Q >   0.5 ) ;
    select( "kaon-" , kaons , Q < -0.5 ) ;

Here all positive kaons (Q>0.5) are selected into the subset named "kaon+" and all negative kaons (Q<-0.5) go to the subset named "kaon-". These subsets again could be subject to further selection/filtering in a similar way.

LoKi allows to perform selection of particles from standard DaVinci containers of particles LHCb::Particle::Vector, LHCb::Particle::ConstVector and LHCb::Particle::Container (also known as LHCb::Particles).

    const LHCb::Particle::ConstVector& particles = ... ;
    Range kaons_1 =  select( "Kaons_1" , particles , abs( ID ) == 321 ) ;
    const LHCb::Particle::Container* event = get<LHCb::Particle::Container>( "..." ) ; 
    Range kaons_2 =  select( "Kaons_2" , event     , 321 == abs( ID ) ) ;

Also any arbitrary sequnce of objects, implicitely convertible to the C++ type const LHCb::Particle* can be used as input for selection of particles:

    /// SEQUENCE is an arbitrary sequence of objects, 
    /// implicitely convertible to 
    /// type Particle*. e.q. std::vector<Particle*>, 
    /// ParticleVector, Particles, std::set<Particle*> etc. 
    SEQUENCE particles = ... ;

    Range kaons =  select( "AllKaons"          ,   // 'tag'
                                      particles.begin () ,   // begin of sequence
                                      particles.end   () ,   // end of sequence 
                                      abs( ID ) == 321   ) ; // cut 

The output of selection (object of type Range) could be directly inspected through the explicit loop over the content of the selected container:

    Range kaons =  select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV ) ;

    // regular C++ loop:
    for( Range::iterator kaon = kaons.begin() ; kaons.end() != kaon ; ++kaon )
        const LHCb::Particle* k = *kaon ;
        /* do something with this raw C++ pointer */


Selection of Monte Carlo Particles

In a similar way one can select Monte Carlo particles (of C++ type LHCb::MCParticle), which satisfy the certain criteria:

    MCRange kaons = mcselect ( "AllMCKaons" , abs( MCID ) == 321 && MCPT > 100 * MeV  ) ;

    MCRange k1 = mcselect ( "mcK+" , kaons , MC3Q >=  1 ) ;
    MCRange k2 = mcselect ( "mcK-"  , kaons , MC3Q <= -1 ) ; 

    // regular C++ loop:
    for ( MCRange::iterator ik1 = k1.begin() ; k1.end() != ik1 ; ++ik1 )
          const LHCb::MCParticle* mc = *k1 ;
          /* do something with this raw C++ pointer */      

The differences with respect the previous case are

  • one needs to use the function mcselect instead of select
  • the return value of this function has C++ type MCRange and behaves like container of const LHCb::MCParticle*
  • for selection one needs to use the special Monte Carlo variables & cuts, e.g. in this example MCID, MCPT and MC3Q.

Selection of Generator Particles

Selection of Vertices

Selection of Monte Carlo Vertices

-- Main.ibelyaev - 11 Jul 2007

Edit | Attach | Watch | Print version | History: r9 | r4 < r3 < r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r2 - 2007-07-11 - VanyaBelyaev
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback