# Difference: LoKiLUG (1 vs. 9)

#### Revision 92008-05-17 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide

Line: 964 to 964
{

// use it!

Changed:
<
<
if ( mc( D0 ) ) { plot ( M ( D0 ) / GeV , "mass of true D0" , M(D0)/GeV, 1.5 , 2.0 ) ; }
>
>
if ( mc( D0 ) ) { plot ( "mass of true D0" , M ( D0 ) / GeV , 1.5 , 2.0 ) ; }
}
Line: 977 to 975
See here

>
>

# Commonly used LoKi::Hybrid::Filters

>
>
The list of commonly used LoKi::Hybrid::Filters could be inspected here.

>
>

-- Vanya Belyaev - 12 Jul 2007 \ No newline at end of file
>
>

-- Vanya BELYAEV - 17 May 2008

#### Revision 82007-07-29 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide

Line: 894 to 894
for ( Loop D0 = loop( "K- pi+", "D0" ) ; D0 ; ++D0 ) {
Changed:
<
<
if ( mcmatch ( D0 , MCD0 ) ) { plot ( M(D0) / GeV , "Mass of true D0 1 " , 1.5 , 2.0 ) ;}
>
>
if ( mcmatch ( D0 , MCD0 ) ) { plot ( M(D0) / GeV , "Mass of true D0 1 " , 1.5 , 2.0 ) ;}
// the same as previous
Changed:
<
<
if ( mcmatch -> match ( D0 , MCD0 ) ) { plot ( M(D0) / GeV, "Mass of true D0 2 " , 1.5 , 2.0 ) ; }
>
>
if ( mcmatch -> match ( D0 , MCD0 ) ) { plot ( M(D0) / GeV, "Mass of true D0 2 " , 1.5 , 2.0 ) ; }
}
Line: 962 to 964
{

// use it!

Changed:
<
<
if ( mc( D0 ) ) { plot ( M ( D0 ) / GeV , "mass of true D0" , M(D0)/GeV, 1.5 , 2.0 ) ; }
>
>
if ( mc( D0 ) ) { plot ( M ( D0 ) / GeV , "mass of true D0" , M(D0)/GeV, 1.5 , 2.0 ) ; }
}

#### Revision 72007-07-28 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide

Line: 76 to 78
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:
Changed:
<
<
• 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
>
>
• 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
Changed:
<
<
and executed by standard KAL executable. The package
>
>
and executed by standard KAL executable. The package
was very successfully used for physics analysis by ARGUS collaboration.
Changed:
<
<
• Pattern and GCombiner packages by Thorsten Glebe.
>
>
• 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
Changed:
<
<
>
>
• 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.
Changed:
<
<
The attractiveness of specialised, physics-oriented code
>
>
The attractiveness of specialized, physics-oriented code
for physics analysis could be demonstrated e.g. with "typical"
Changed:
<
<
code fragment in KAL:
>
>
code fragment in KAL:
%SYNTAX{ syntax="fortran" numbered="1000" numstep="10"}%
>
>
HYPOTH E+ MU+ PI+ 5 K+ PROTON

IDENT PI+ PI+

Line: 119 to 122
ENDSEL

GO 1000000

>
>
%ENDSYNTAX%
Changed:
<
<
This KAL pseudo-code gives
>
>
This KAL pseudo-code gives
an example of self-explanatory code. The physical content of selection of ,
Line: 134 to 138
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
Changed:
<
<
from T. Glebe's Pattern of
>
>
from T. Glebe's Pattern of
reconstruction: %SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
>
>
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 ) ;
>
>
%ENDSYNTAX%
Line: 146 to 156

This code fragment is not so transparent as specialized

Changed:
<
<
KAL pseudo-code but it is easy-to-read,
>
>
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
Line: 171 to 185
The physical content of these lines is quite transparent. Again I suppose that it is not obscured with C++ semantics.
Changed:
<
<
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
>
>
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

Changed:
<
<
developed withing DaVinci project.
>
>
developed within DaVinci project.

Changed:
<
<
Since LoKi is just a thin layer, all DaVinci tools are available in LoKi and could be directly invoked and manipulated.
>
>
Since LoKi is just a thin layer, all DaVinci toolsare 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.
>
>

### Acknowledgments

As a last line of this chapter I'd like to thank Galina Pakhlova, Andrey Tsaregorodtsev and Sergey Barsuk
Changed:
<
<
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 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,
Line: 205 to 222
Gerhard Raven, Thomas Ruf, Hugo Ruiz Perez,
Changed:
<
<
Jeroen van Tilburg and
>
>
Jeroen van Tilburg, and
Benoit Viaud.
Changed:
<
<
It is the real pleasure to thank the leaders of ITEP/Moscow, CERN-LBD, LAPP/Annecy and Syracuse University teams for the kind support.
>
>
It is the real pleasure to thank the leaders of ITEP/Moscow (Andrey Golutvin), CERN-LBD (Hans-Jurgen Hilke and Hans Dijkstra), LAPP/Annecy (Marie-Noelle Minard and Boleslav Pietrzyk) and Syracuse University (Sheldon Stone and Tomasz Skwarnicki) teams for the kind support.

### Who is LoKi?

• Loki is a god of wit and mischief in Norse mythology
Line: 244 to 267

LoKi allows to select/filter a subset of reconstructed

Changed:
<
<
particles (of C++ type LHCb::Particle) which fulfills
>
>
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: %SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Line: 257 to 283
These particles are copied into internal local LoKi storage and could be accessed later using the symbolic name "AllKaons".
Changed:
<
<
In this example ID and PT are predefined
>
>
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
Line: 270 to 296
LoKi defines many frequently used variables and set of the regular mathematical operation on them '+', '-', '*', '/' and all elementary functions, like
Changed:
<
<
sin, cos, log, atan, atan2, pow etc,
>
>
sin, cos, log, atan, atan2, pow etc,
which could be used for construction of variables of
Changed:
<
<
the arbitrary complexity. Cuts and variables are discussed in
>
>
the arbitrary complexity. Cuts and variables are discussed in
detail in subsequent chapters

Indeed the function select has a return value of type Range,

Line: 340 to 377
In a similar way one can select Monte Carlo particles (of C++ type LHCb::MCParticle), which satisfy the certain criteria:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
MCRange kaons = mcselect ( "AllMCKaons" , abs( MCID ) == 321 && MCPT > 100 * MeV ) ;
Line: 354 to 392
/* do something with this raw C++ pointer */ }
Changed:
<
<
>
>
%ENDSYNTAX%
The differences with respect the previous case are
• one needs to use the function mcselect instead of select
Line: 368 to 406
Similar to the selection of reconstructed particles and the selection of Monte Carlo particles one can perform the selection of Generator particles (of C++ type HepMC::GenParticle):
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
GRange kaons = gselect ( "AllGenKaons" , abs( GID ) == 321 && GPT > 100 * MeV ) ;
Line: 382 to 420
/* do something with this raw C++ pointer */ }
Changed:
<
<
>
>
%ENDSYNTAX%
One sees that the C++ code essentially the same with the minor difference:
• one needs to use the function gselect instead of select and mcselect
• the return value of this function has C++ type GRange and behaves like the container of const HepMC::GenParticle*
Line: 394 to 433

### Selection of Vertices

The similar approach is used for selection/filtering of vertices (of C++ type LHCb::VertexBase):

Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
VRange vs = vselect( "GoodPVs" , PRIMARY && 5 < VTRACKS && VCHI2 / VDOF < 10 );

Changed:
<
<
>
>
%ENDSYNTAX%
Here from all vertices loaded by DaVinci one selects only the vertices tagged as "Primary Vertex" (PRIMARY) and constructed from more that 5 tracks (5<VTRACKS)
Line: 430 to 470
LHCb::RecVertex::ConstVector, LHCb::RecVertex::Container and from arbitary sequence of objects, convertible to const LHCb::VertexBase*:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
VRange vertices_1 = ... ; VRange vs1 =
Line: 453 to 493
vertices_3.end () , // end of input sequence PRIMARY && 5 < VTRACKS ); // cut

Changed:
<
<
>
>
%ENDSYNTAX%
In summary, for selection of vertices:
• one needs to use the function vselect
Line: 486 to 521
container of objects the object which maximizes or minimizes some function. The selection of the primary vertex with the maximal multiplicity could be considered as typical example:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// get all primary vertices VRange vrtxs = vselect( "GoodPVs" , PRIMARY ) ;

const LHCb::VertexBase* vertex = select_max( vrtxs , VTRACKS ) ;

Changed:
<
<
>
>
%ENDSYNTAX%
Here from the preselected sample of primary vertices vrtxs one selects only one vertex which maximizes Vertex function VTRACKS with value equal to the number of tracks participating in this primary vertex.
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// get all primary vertices: VRange vrtxs = vselect( "GoodPVs" , PRIMARY );
Line: 510 to 545
// find the primatry vertex with minimal B-impact parameter const LHCb::VertexBase* vertex = select_min( vrtxs , VIP( B , geo() ) ) ;

Changed:
<
<
>
>
%ENDSYNTAX%
Here from the preselected sample of primary vertices vrtxs one selects the only vertex which minimize function VIP, with value equal to the impact parameter of
Line: 518 to 553

The templated methods select_max and select_min are type-blind and they could be applied e.g. to the containers of particles:

Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Range kaons = select( .... );

const LHCb::Particle* kaon = select_min( kaons , abs( PY ) + sin( PX ) ) ;

Changed:
<
<
>
>
%ENDSYNTAX%
Here from the container of preselected kaons the particle, which gives the minimal value of funny combination
Changed:
<
<
$\left|{\mathrm{p_y}}\right|+ \sin {\mathrm{p_x}}$ is selected.
>
>
is selected.
The methods select_min_ and =select_max also allow the conditional selection of minimal/maximal candidate:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
MCRange kaons = mcselect( "kplus" , MCID == "K+" ) ;
Line: 547 to 582
/* do something with this raw C++ pointer */ }
>
>
%ENDSYNTAX%

Deleted:
<
<
Here the maximum is searched only within the particles whcih satisfy the cut (0<MCPZ) - the z-component of particle momenta must be positive..
Line: 557 to 592
All selection functions, described above returns the light pseudocontainer of selected objects. Alternatively the selection result could be accessed using the unique tag (used as the first
Changed:
<
<
string argument of the functions *select) and the function *selected:
>
>
string argument of the functions select) and the function selected: %SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// get all previously selected particles, tagged as "MyGoodKaons": Range goodK = selected ( "MyGoodKaons" ) ;
Line: 569 to 604
// get all previosly selected Generator particles, tagged as "My good b-quarks": GRange bquarks = mcselected ("My good b-quarks") ;

Changed:
<
<
>
>
%ENDSYNTAX%

Line: 585 to 618
Above it has been already shown how to perform simple looping over the selected range of particles:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Range kaons = select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV );
Line: 595 to 628
/* do something with this raw C++ pointer */ }
Changed:
<
<
>
>
%ENDSYNTAX%
Equivalently one can use methods Range::operator(), Range::operator[] or Range::at():
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Range kaons = select ( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV );
Line: 609 to 642
const LHCb::Particle* k3 = kaons .at ( index ) ; // use Range::at }

Changed:
<
<
>
>
%ENDSYNTAX%
The result of operators are not defined for invalid index, and Range::at method throws an exception for invalid index.

In principle one could combine these one-particle loops to get the

Line: 622 to 656
using the special object Loop. All native C++ semantics for looping is supported by this object, e.g. for native C++ for -loop:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// loop over all "kaon- kaon+ "combinations for ( Loop phi = loop ( "kaon- kaon+" ) ; phi ; ++phi )
Line: 630 to 664
/* do something with the combination */ }

Changed:
<
<
>
>
%ENDSYNTAX%
The while -form of the native C++ loop is also supported:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Loop phi = loop( "kaon- kaon+" ) ; while ( phi )
Line: 642 to 677
++phi ; // go to the next valid combination }

Changed:
<
<
>
>
%ENDSYNTAX%
The parameter of loop function is the selection formula
Line: 654 to 689
within the loop over multiparticle combinations, e.g. for the following loop the given pair of two photons will appear only once:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Loop pi0 = loop( "gamma gamma" ) ; while ( pi0 )
Line: 664 to 699
++pi0 ; // go to the next valid combination }

Changed:
<
<
>
>
%ENDSYNTAX%
Internally LoKi eliminates such double counting through the discrimination of non-ordered combinations of the particles of the same type.
Line: 677 to 712

For access to the daughter particles (the selection components) one could use following constructions:

Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 ) {
Line: 687 to 722
const LHCb::Particle* pim = D0(4) ; // the fourth daughter particle }

Changed:
<
<
>
>
%ENDSYNTAX%
Please pay attention that the indices for daughter particles starts from 1, because this is more consistent with actual notions "the first daughter particle", "the second daughter particle", etc. The index 0 is reserved for the whole combination. Alternatively one could use other functions with a bit more verbose semantics:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 ) {
Line: 704 to 739
const LHCb::Particle* pim = D0->particle(4) ; // the fourth daughter }

Changed:
<
<
>
>
%ENDSYNTAX%
Since the results of all these operations are raw C++ pointers to LHCb::Particle= objects, one could effectively reuse the functions & cuts for extraction the useful information:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 ) {
Line: 717 to 752
const double PTpm = PT( D0(4) ) ; // Momentum of "pi-" }

Changed:
<
<
>
>
%ENDSYNTAX%
Plenty of methods exist for evaluation of different kinematic quantities of different combinations of daughter particles:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 ) {
Line: 735 to 770
doule m13 = D0->m(1,3) ; // mass of 1st and 3rd particles }

Changed:
<
<
>
>
%ENDSYNTAX%
Alternatively to the convenient short-cut methods Loop::p, Loop::m one could use the equivalent methods Loop::momentum and Loop::mass respectively.
Line: 747 to 783
to be supplied with the type of the particle. The information on the particle type can be introduced into the loop in the following different ways:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// particle name for ( Loop D0 = loop( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 ) { ... }
Line: 771 to 809
// perform a loop: for ( ; D0 ; ++D0 ) { ... }

Changed:
<
<
>
>
%ENDSYNTAX%
For properly instrumented looping construction one has an access to the information about the effective mother particle of the combination:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop D0 = loop ( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 ) {
Line: 787 to 825
const LHCb::Vertex* v_2 = D0->vertex() ; }

Changed:
<
<
>
>
%ENDSYNTAX%
The example above shows several alternative ways for accessing information on "the effective particle" and
Line: 797 to 835
to the types const LHCb::Particle* and const LHCb::Vertex* allows to apply all machinery of Particle and Vertex functions and cuts to the looping construction:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop D0 = loop( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 ) { double mass = M( D0 ) / GeV ; // mass in GeV
Line: 805 to 843
double pt = PT ( D0 ) ; // transverse momentum }
Changed:
<
<
>
>
%ENDSYNTAX%

### Saving of the interesting combinations

Changed:
<
<
Every interesting combination of particles could be saved for future reuse in LoKi and/or DaVinci:
>
>
Every interesting combination of particles could be saved for future reuse in LoKi and/or DaVinci: %SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
for ( Loop phi = loop( "kaon- kaon+" , "phi(1020)" ) ; phi ; ++phi ) { if( M( phi ) < 1.050 * Gev ) { phi->save( "phi" ) ; } }

Changed:
<
<
>
>
%ENDSYNTAX%
When particle is saved in internal LoKi storage, it is simultaneously saved into DaVinci's Desktop Tool.
Line: 848 to 885
The helper utility MCMatch could be used to check if given reconstructed particle has the match with given Monte Carlo particle:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
MCMatch mcmatch = mcTruth ("My MC-truth matcher") ;
Line: 856 to 893
for ( Loop D0 = loop( "K- pi+", "D0" ) ; D0 ; ++D0 ) {
>
>
if ( mcmatch( D0 , MCD0 ) ) { plot ( M(D0) / GeV , "Mass of true D0 1 " , 1.5 , 2.0 ) ;}
>
>
// the same as previous if ( mcmatch->match( D0 , MCD0 ) ) { plot ( M(D0) / GeV, "Mass of true D0 2 " , 1.5 , 2.0 ) ;}
>
>
}
Changed:
<
<
>
>
%ENDSYNTAX%
The actual Monte Carlo matching procedure is described in detail here.

MCMatch object could be used for repetitive matching with sequences of arbitrary type of Monte Carlo and reconstructed particles:

Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
// some 'sequence' or 'range' type typedef std::vector MCSEQ ;
Line: 900 to 941
mcps.begin () , // begin of MC sequence mcps.end () ) ; // end of MC sequence

Changed:
<
<
>
>
%ENDSYNTAX%

The methods described above are template, and therefore they could be

Line: 910 to 951
Of course in the spirit of LoKi is to provide the same functionality in a more useful and elegant way as ordinary predicate or cut:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
const LHCb::MCParticle* MCD0 = ... ;

Line: 919 to 960
for ( Loop D0 = loop( "K- pi+", "D0" ) ; D0 ; ++D0 ) {
>
>
// use it! if ( mc( D0 ) ) { plot ( M(D0) / GeV , "mass of true D0" , M(D0)/GeV, 1.5 , 2.0 ) ;}
>
>
}
Changed:
<
<
>
>
%ENDSYNTAX%
The latter way is especially convenient for analysis.
Changed:
<
<

>
>

# LoKi Reference Manual

See here

#### Revision 62007-07-16 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"
Changed:
<
<

>
>

>
>

>
>

Line: 21 to 23

Changed:
<
<

>
>

# LoKi User Guide

Changed:
<
<

>
>

## Introduction

All off-line OO software for simulation,
Line: 52 to 54
Often a simple operation corresponding to one "physics" statement results in an enormous code with complicated and probably non-obvious content:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
ParticleVector::const_iterator im; for ( im = vDsK.begin(); im = vDsK.end(); im++ ) { if((*im)->particleID().pid() == m_DsPlusID||
Line: 64 to 66
return StatusCode::FAILURE; } }
Changed:
<
<
>
>
%ENDSYNTAX%
The usage of comments becomes mandatory for understanding makes the code even longer and again results in additional complexity.
Line: 97 to 98
The attractiveness of specialised, physics-oriented code for physics analysis could be demonstrated e.g. with "typical" code fragment in KAL:
Changed:
<
<
>
>
%SYNTAX{ syntax="fortran" numbered="1000" numstep="10"}%
HYPOTH E+ MU+ PI+ 5 K+ PROTON

IDENT PI+ PI+

Changed:
<
<
IDENT K+ K+
>
>
IDENT K+ K
IDENT PROTON PROTON IDENT E+ E+ IDENT MU+ MU+
Line: 117 to 119
ENDSEL

GO 1000000

Changed:
<
<
>
>
%ENDSYNTAX%
This KAL pseudo-code gives an example of self-explanatory code. The physical content of selection of
Changed:
<
<
${\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
>
>
, followed by decay is clear and unambigously visible between these lines. Indeed no comments
are needed for understanding the analysis within 2 minutes.
Line: 133 to 135
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
Changed:
<
<
${\mathrm{K}}^0_{\mathrm{S}}\rightarrow \pi^+\pi^-$ reconstruction:
>
>
reconstruction: %SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
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 ) ;
Changed:
<
<
>
>
%ENDSYNTAX%

This code fragment is not so transparent as specialized

Line: 154 to 155
Here it is a good moment to jump to the end of the whole story and present some LoKi fragment for illustration:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
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"); }
Line: 163 to 165
} for ( Loop Dstar = loop( "D0 Pi+" , "D*+" ) ; Dstar ; ++Dstar ) {
Changed:
<
<
plot ( M( Dstar ) / GeV , " Mass of D0 pi+ " , 2.0 , 2.1 , 100 );
>
>
plot ( M ( Dstar ) / GeV , " Mass of D0 pi+ " , 2.0 , 2.1 ) ;
}
Changed:
<
<
>
>
%ENDSYNTAX%
The physical content of these lines is quite transparent. Again I suppose that it is not obscured with C++ semantics.
Line: 209 to 210
It is the real pleasure to thank the leaders of ITEP/Moscow, CERN-LBD, LAPP/Annecy and Syracuse University teams for the kind support.
Changed:
<
<

>
>

### Who is LoKi?

• Loki is a god of wit and mischief in Norse mythology
• LoKi could be interpreted as Loops&Kinematics
Changed:
<
<

>
>

## LoKi ingredients

Typical analysis algorithm consists of quite complex combination of the following elementary actions:
Line: 236 to 237
LoKi has been designed to attack all these five major actions.
Changed:
<
<

>
>

## Selection

Changed:
<
<

>
>

### 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:

Changed:
<
<

>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV ) ;
Changed:
<
<
>
>
%ENDSYNTAX%
Here from all particles, loaded by DaVinci, the subset of particles identified as charged kaons (abs(ID)==321) with transverse momentum greater
Line: 283 to 282
sub-selections. The following example illustrates the idea: the selected sample of kaons is subdivided into samples of positive and negative kaons:
Changed:
<
<
>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Range kaons = select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV ); select( "kaon+" , kaons , Q > 0.5 ) ; select( "kaon-" , kaons , Q < -0.5 ) ;
Changed:
<
<
>
>
%ENDSYNTAX%
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
Line: 300 to 297
LHCb::Particle::Vector, LHCb::Particle::ConstVector and LHCb::Particle::Container (also known as LHCb::Particles).
Changed:
<
<

>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
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 ) ) ;

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

>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
/// SEQUENCE is an arbitrary sequence of objects,
Changed:
<
<
/// implicitely convertible to /// type Particle*. e.q. std::vector<Particle*>, /// ParticleVector, Particles, std::set<Particle*> etc.
>
>
/// implicitely convertible to type const LHCb::Particle* /// e.q. std::vector<LHCb::Particle*>, /// LHCb::Particle::ConstVector, LHCb::Particles, std::set<LHCb::Particle*> etc.
SEQUENCE particles = ... ;
Changed:
<
<
Range kaons = select( "AllKaons" , // 'tag'
>
>
Range kaons = select ( "AllKaons" , // 'tag'
particles.begin () , // begin of sequence particles.end () , // end of sequence abs( ID ) == 321 ) ; // cut
Changed:
<
<
>
>
%ENDSYNTAX%
The output of selection (object of type Range) could be directly inspected through the explicit loop over the content of the selected container:
Changed:
<
<


>
>
%SYNTAX{ syntax="cpp" numbered="1000" numstep="10"}%
Range kaons = select( "AllKaons" , abs( ID ) == 321 && PT > 100 * MeV ) ;

// regular C++ loop:

Line: 341 to 333
const LHCb::Particle* k = *kaon ; /* do something with this raw C++ pointer */ }
Changed:
<
<
>
>
%ENDSYNTAX%

Changed:
<
<

>
>

### 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:
Line: 372 to 363

Changed:
<
<

>
>

### Selection of Generator Particles

Similar to the selection of reconstructed particles and the selection of Monte Carlo particles one can perform the selection of
Line: 400 to 391

Changed:
<
<

>
>

### Selection of Vertices

The similar approach is used for selection/filtering of vertices (of C++ type LHCb::VertexBase):
Line: 475 to 466

Changed:
<
<

>
>

### Selection of Monte Carlo Vertices and Generator Vertices

The selection of Monte Carlo Vertices and Generator Vertices is performed similar to the the selection of reconstructed Vertices with following difference:
Line: 489 to 480

Changed:
<
<

>
>

### Selection of minimal/maximal candidate

It is not unusual to select from some sequence or container of objects the object which maximizes or minimizes
Line: 562 to 553

Changed:
<
<

>
>

All selection functions, described above returns the light pseudocontainer of selected objects. Alternatively the selection result could be accessed using the unique tag (used as the first
Line: 584 to 575

Changed:
<
<

>
>

## Loops

Changed:
<
<

>
>

### Looping over the reconstructed particles

Changed:
<
<
>
>

#### Simple one-particle loops

Above it has been already shown how to perform simple looping over the selected range of particles:
Line: 625 to 616
effective loops over multi-particle combinations. But this gives no essential gain.

Changed:
<
<
>
>

#### Loops over the multi-particle combinations

Looping over multi-particle combinations is performed using the special object Loop.
Line: 679 to 670
combinations of the particles of the same type.
Changed:
<
<

>
>

Inside the loop there are several ways to access the information about the properties of the combination.
Changed:
<
<
>
>

For access to the daughter particles (the selection components) one could use following constructions:
Line: 749 to 740
Loop::m one could use the equivalent methods Loop::momentum and Loop::mass respectively.

Changed:
<
<
>
>

Access to information on the effective mother particle of the combination requires the call of loop method
Line: 840 to 831
containers/selections.

Changed:
<
<

>
>

Changed:
<
<

>
>

## Usage of kinematic constraints in LoKi

Changed:
<
<

>
>

Changed:
<
<

>
>

### Monte Carlo truth matching

LoKi offers fast, easy, flexible and configurable access to Monte Carlo truth information.
Line: 936 to 927
The latter way is especially convenient for analysis.
Deleted:
<
<

## LoKi Reference Manual

Changed:
<
<

### LoKi's Particle Functions

ALL
The trivial "select-all" predicate of C++ type LoKi::BooleanConstant(true), which always returns true
ABSID
The simple function (of type LoKi::Particles::AbsIdentifier()), which returns the absolute value of PDG-identifier of the particle:
   const LHCb::Particle* p = ... ;
const double absid = ABSID( p ) ;

For the invalid argument LoKi::Constanst::InvalidID is returned.The special comparison operators against std::string and LHb::ParticleID objects are defined:
   Range kaons = select ( "kaons" , "K+" == ABSID ) ;
Range muons = select ( "muons" , LHCb::ParticleID( 13 ) == ABSID ) ;

EQUALTO
Simple predicate ( of C++ type LoKi::EqualToValue) which checks if the value of the certain function equal to some predefined value:
   Range k1 = select ( "positive" , EQUALTO( Q , +1.0 ) ) ;
Range k2 = select ( "positive" , Q == +1 ) ; ///< the same

HASKEY
Predicate which returns true if the argument has the assigned key, see also KEY
KEY
Function, which returns the value of the assigned key. For invalid arguments, of if no key is assigned LoKi::Constants::InvalidKey is returned, see also HASKEY
ID
The simple function (of type LoKi::Particles::Identifier()), which returns the value of PDG-identifier of the particle:
   const LHCb::Particle* p = ... ;
const double id = ID( p ) ;

For the invalid argument LoKi::Constanst::InvalidID is returned.The special comparison operators against std::string and LHb::ParticleID objects are defined:
   Range kaons = select ( "kaons" , "K+" == ID ) ;
Range muons = select ( "muons" , LHCb::ParticleID( 13 ) == ID ) ;

NONE
The trivial "select-none" predicate of C++ type LoKi::BooleanConstant(false), which always returns false
ONE
The trivial function of C++ type LoKi::Constant(1), which always returns 1
PALL
alias for ALL, see here
PFALSE
alias for NONE, see here
PNONE
alias for NONE, see here
PONE
alias for ONE, see here
PSWITCH
alias for SWITCH, see here
PTRUE
alias for ALL, see here
PZERO
alias for ZERO, see here
SWITCH
The function (C++ type LoKi::Switch), which acts according the rule: result = condition ? function1 : function2:
   Fun signedPT = SWITCH( 0 < Q , PT , -1*PT ) ;

VALID
The trivial function of C++ type LoKi::Valid(), which check the validity of the argument:
   const std::vector<const LHCb::Particle*>& p = ... ;
// check for invalid pointers:
if ( std::find_if ( p.begin() , p.end() , !VALID ) != p.end() ) { ... there are null pointers ... }

ZERO
The trivial function of C++ type LoKi::Constant(0), which always returns 0
>
>
See here

#### Revision 52007-07-15 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide & Reference Manual

Line: 945 to 945

>
>

### LoKi's Particle Functions

ALL
The trivial "select-all" predicate of C++ type LoKi::BooleanConstant(true), which always returns true
ABSID
The simple function (of type LoKi::Particles::AbsIdentifier()), which returns the absolute value of PDG-identifier of the particle:
   const LHCb::Particle* p = ... ;
const double absid = ABSID( p ) ;

For the invalid argument LoKi::Constanst::InvalidID is returned.The special comparison operators against std::string and LHb::ParticleID objects are defined:
   Range kaons = select ( "kaons" , "K+" == ABSID ) ;
Range muons = select ( "muons" , LHCb::ParticleID( 13 ) == ABSID ) ;

EQUALTO
Simple predicate ( of C++ type LoKi::EqualToValue) which checks if the value of the certain function equal to some predefined value:
   Range k1 = select ( "positive" , EQUALTO( Q , +1.0 ) ) ;
Range k2 = select ( "positive" , Q == +1 ) ; ///< the same

HASKEY
Predicate which returns true if the argument has the assigned key, see also KEY
KEY
Function, which returns the value of the assigned key. For invalid arguments, of if no key is assigned LoKi::Constants::InvalidKey is returned, see also HASKEY
ID
The simple function (of type LoKi::Particles::Identifier()), which returns the value of PDG-identifier of the particle:
   const LHCb::Particle* p = ... ;
const double id = ID( p ) ;

For the invalid argument LoKi::Constanst::InvalidID is returned.The special comparison operators against std::string and LHb::ParticleID objects are defined:
   Range kaons = select ( "kaons" , "K+" == ID ) ;
Range muons = select ( "muons" , LHCb::ParticleID( 13 ) == ID ) ;

NONE
The trivial "select-none" predicate of C++ type LoKi::BooleanConstant(false), which always returns false
ONE
The trivial function of C++ type LoKi::Constant(1), which always returns 1
PALL
alias for ALL, see here
PFALSE
alias for NONE, see here
PNONE
alias for NONE, see here
PONE
alias for ONE, see here
PSWITCH
alias for SWITCH, see here
PTRUE
alias for ALL, see here
PZERO
alias for ZERO, see here
SWITCH
The function (C++ type LoKi::Switch), which acts according the rule: result = condition ? function1 : function2:
   Fun signedPT = SWITCH( 0 < Q , PT , -1*PT ) ;

VALID
The trivial function of C++ type LoKi::Valid(), which check the validity of the argument:
   const std::vector<const LHCb::Particle*>& p = ... ;
// check for invalid pointers:
if ( std::find_if ( p.begin() , p.end() , !VALID ) != p.end() ) { ... there are null pointers ... }

ZERO
The trivial function of C++ type LoKi::Constant(0), which always returns 0

Deleted:
<
<

-- Vanya Belyaev - 12 Jul 2007

#### Revision 42007-07-12 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"
Changed:
<
<

>
>

# LoKi User Guide & Reference Manual

>
>

### Abstract

LoKi is a package for the simple and user-friendly data analysis. LoKi is based on Gaudi architecture.
Line: 15 to 19
>
>

Line: 931 to 937

Changed:
<
<

>
>

## LoKi Reference Manual

Changed:
<
<
-- Main.ibelyaev - 11 Jul 2007
>
>

-- Vanya Belyaev - 12 Jul 2007

#### Revision 32007-07-11 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide

Line: 15 to 15
Changed:
<
<

>
>

## LoKi User Guide

### Introduction

Line: 200 to 200
Hugo Ruiz Perez, Jeroen van Tilburg and Benoit Viaud.
Changed:
<
<
It is a pleasure to thank the leaders of ITEP/Moscow, CERN-LBD,
>
>
It is the real pleasure to thank the leaders of ITEP/Moscow, CERN-LBD,
LAPP/Annecy and Syracuse University teams for the kind support.
>
>

#### Who is LoKi?

• Loki is a god of wit and mischief in Norse mythology
• LoKi could be interpreted as Loops&Kinematics

### LoKi ingredients

Line: 336 to 338

>
>

#### Selection of Monte Carlo Particles

Deleted:
<
<
In a similar way one can select Monte Carlo particles (of C++ type LHCb::MCParticle), which satisfy the certain criteria:
Line: 359 to 361
The differences with respect the previous case are
• one needs to use the function mcselect instead of select
Changed:
<
<
• the return value of this function has C++ type MCRange and behaves like container of const LHCb::MCParticle*
>
>
• the return value of this function has C++ type MCRange and behaves like the 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

>
>
Similar to the selection of reconstructed particles and the selection of Monte Carlo particles one can perform the selection of Generator particles (of C++ type HepMC::GenParticle):

Changed:
<
<

#### Selection of Generator Particles

>
>
GRange kaons = gselect ( "AllGenKaons" , abs( GID ) == 321 && GPT > 100 * MeV ) ;

GRange k1 = gselect ( "genK+" , kaons , G3Q >= 1 ) ; GRange k2 = gselect ( "genK-" , kaons , G3Q <= -1 ) ;

// regular C++ loop: for ( GRange::iterator ik1 = k1.begin() ; k1.end() = ik1 ; ++ik1 ) { const HepMC::GenParticle* gen = *k1 ; /* do something with this raw C++ pointer */ }

One sees that the C++ code essentially the same with the minor difference:

• one needs to use the function gselect instead of select and mcselect
• the return value of this function has C++ type GRange and behaves like the container of const HepMC::GenParticle*
• for selection one needs to use the special Generator variables & cuts, e.g. in this example GID, GPT and G3Q.

Changed:
<
<

#### Selection of Monte Carlo Vertices

>
>
The similar approach is used for selection/filtering of vertices (of C++ type LHCb::VertexBase):

VRange vs  = vselect( "GoodPVs" ,
PRIMARY && 5 < VTRACKS && VCHI2 / VDOF < 10 );


Here from all vertices loaded by DaVinci one selects only the vertices tagged as "Primary Vertex" (PRIMARY) and constructed from more that 5 tracks (5<VTRACKS) and with $\chi^2/{\mathrm{nDoF}}$ less than 10 (VCHI2/VDOF<10). This set of selected vertices is named as "GoodPVs".

Again PRIMARY, VTRACKS, VCHI2 and VDOF are predefined LoKi Vertex functions & cuts. It is internal convention of LoKi that all predefined functions, types and methods for vertices start their names from capital letter V. As an example one see type VRange for a light pseudo-container of const LHCb::VertexBase*, function vselect and all variables for vertices.

Also there exist the variants of vselect methods, which allow the subselection of vertices from already selected ranges of vertices (C++ type VRange), standard DaVinci containers (C++ types LHCb::VertexBase::Vector, LHCb::VertexBase::ConstVector, LHCb::VertexBase::Container, LHCb::Vertex::Vector, LHCb::Vertex::ConstVector, LHCb::Vertex::Container, LHCb::RecVertex::Vector, LHCb::RecVertex::ConstVector, LHCb::RecVertex::Container and from arbitary sequence of objects, convertible to const LHCb::VertexBase*:


VRange vertices_1 = ... ;
VRange vs1 =
vselect(  "GoodPVs1"  ,              // 'tag'
vertices_1  ,              // input vertices
PRIMARY && 5 < VTRACKS  ); // cut

LHCb::VertexBase::ConstVector vertices_2 = ... ;
VRange vs2 =
vselect(  "GoodPVs2"  ,              // 'tag'
vertices_2  ,              // input vertices
PRIMARY && 5 < VTRACKS  ); // cut

/// arbitrary sequence of ojbects, implicitely convertible to
/// type LHCb::VertexBase*, e.g. std::vector<LHCb::VertexBase*>
SEQUENCE vertices_3 = ... ;
VRange vs3 =
vselect(  "GoodPVs4"          ,      // 'tag'
vertices_3.begin () ,      // begin of input sequence
vertices_3.end   () ,      // end of input sequence
PRIMARY && 5 < VTRACKS  ); // cut



In summary, for selection of vertices:

• one needs to use the function vselect
• the return value of this function has C++ type VRange and behaves like the container of const LHCb::VertexBase*
• for selection one needs to use the special Vertex variables & cuts, e.g. in this example PRIMARY, VTRACKS, VCHI2 and VDOF.

#### Selection of Monte Carlo Vertices and Generator Vertices

The selection of Monte Carlo Vertices and Generator Vertices is performed similar to the the selection of reconstructed Vertices with following difference:

• one needs to use the functions mcvselect and gvselect for Monte Carlo Vertices and Generator Vertices respectively
• the return value of this function has C++ type MCVRange (GVRange)and behaves like the container of const LHCb::MCVertex* (const HepMC::GenVertex*) for Monte Carlo Vertices and Generator Vertices respectively
• for selection one needs to use the special Monte Carlo Vertex variables & cuts or Generator Vertex variables & cuts

#### Selection of minimal/maximal candidate

It is not unusual to select from some sequence or container of objects the object which maximizes or minimizes some function. The selection of the primary vertex with the maximal multiplicity could be considered as typical example:


// get all primary vertices
VRange vrtxs     = vselect( "GoodPVs" , PRIMARY ) ;

const  LHCb::VertexBase* vertex  = select_max( vrtxs , VTRACKS ) ;


Here from the preselected sample of primary vertices vrtxs one selects only one vertex which maximizes Vertex function VTRACKS with value equal to the number of tracks participating in this primary vertex.


// get all primary vertices:
VRange vrtxs           = vselect( "GoodPVs" , PRIMARY );

// get B-candidate
const LHCb::Particle* B = ...

// find the primatry vertex with minimal B-impact parameter
const LHCb::VertexBase* vertex  = select_min( vrtxs , VIP( B , geo() ) ) ;


Here from the preselected sample of primary vertices vrtxs one selects the only vertex which minimize function VIP, with value equal to the impact parameter of the given particle (e.g. B-candidate) with respect to the vertex.

The templated methods select_max and select_min are type-blind and they could be applied e.g. to the containers of particles:


Range kaons  = select( .... );

const LHCb::Particle* kaon  = select_min( kaons  , abs( PY ) + sin( PX )   ) ;


Here from the container of preselected kaons the particle, which gives the minimal value of funny combination $\left|{\mathrm{p_y}}\right|+ \sin {\mathrm{p_x}}$ is selected.

The methods select_min_ and =select_max also allow the conditional selection of minimal/maximal candidate:


MCRange kaons = mcselect( "kplus" , MCID == "K+" ) ;

MCRange::iterator igood = select_max
( kaons.begin() ,    // begin of the sequence
kaons.end  () ,    // end of the sequence
MCPT          ,    // function to be maximized
0 < MCPZ      ) ;  // condition/cut

if ( kaons.end() != igood  )
{
const LHCb::MCParticle* good = *igood ;
/* do something with this raw C++ pointer */
}


Here the maximum is searched only within the particles whcih satisfy the cut (0<MCPZ) - the z-component of particle momenta must be positive..

All selection functions, described above returns the light pseudocontainer of selected objects. Alternatively the selection result could be accessed using the unique tag (used as the first string argument of the functions *select) and the function *selected:


// get all previously selected particles, tagged as "MyGoodKaons":
Range goodK = selected ( "MyGoodKaons" ) ;

// get all previosly selected Monte Carlo particles, tagged as "TrueMCkaons":
MCRange mcK = mcselected ( "TrueMCkaons" ) ;

// get all previosly selected Generator particles, tagged as "My good b-quarks":
GRange bquarks = mcselected ("My good b-quarks") ;



### Loops

#### Looping over the reconstructed particles

##### Simple one-particle loops

Above it has been already shown how to perform simple looping over the selected range of particles:


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

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



Equivalently one can use methods Range::operator(), Range::operator[] or Range::at():


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

for ( unsigned int index = 0 ; index < kaons.size() ; ++index )
{
const LHCb::Particle* k1 = kaons     ( index ) ;  // use Range::operator()
const LHCb::Particle* k2 = kaons     [ index ] ;  // use Range::operator[]
const LHCb::Particle* k3 = kaons .at ( index ) ; // use Range::at
}


The result of operators are not defined for invalid index, and Range::at method throws an exception for invalid index.

In principle one could combine these one-particle loops to get the effective loops over multi-particle combinations. But this gives no essential gain.

##### Loops over the multi-particle combinations

Looping over multi-particle combinations is performed using the special object Loop. All native C++ semantics for looping is supported by this object, e.g. for native C++ for -loop:


// loop over all "kaon- kaon+ "combinations
for  ( Loop phi = loop ( "kaon- kaon+" ) ; phi ; ++phi )
{
/* do something with the combination */
}


The while -form of the native C++ loop is also supported:

Loop phi = loop( "kaon- kaon+" ) ;
while ( phi )
{
/* do something with the combination */

++phi ; // go to the next valid combination
}



The parameter of loop function is the selection formula (blank or comma separated list of particle tags). All items in the selection formula must be known for LoKi, e.g. previously selected using select functions.

LoKi takes care about the multiple counting within the loop over multiparticle combinations, e.g. for the following loop the given pair of two photons will appear only once:


Loop pi0 = loop( "gamma gamma" ) ;
while ( pi0 )
{
/* do something with the combination */

++pi0 ; // go to the next valid combination
}


Internally LoKi eliminates such double counting through the discrimination of non-ordered combinations of the particles of the same type.

Inside the loop there are several ways to access the information about the properties of the combination.

For access to the daughter particles (the selection components) one could use following constructions:


for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 )
{
const LHCb::Particle* kaon = D0(1) ; // the first daughter particle
const LHCb::Particle* piP1 = D0(2) ; // the first positively charged pion
const LHCb::Particle* piP2 = D0(3) ; // the second positively charged pion
const LHCb::Particle* pim  = D0(4) ; // the fourth daughter particle
}


Please pay attention that the indices for daughter particles starts from 1, because this is more consistent with actual notions "the first daughter particle", "the second daughter particle", etc. The index 0 is reserved for the whole combination. Alternatively one could use other functions with a bit more verbose semantics:

for( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 )
{
const LHCb::Particle* kaon = D0->daughter(1) ; // the first daughter
const LHCb::Particle* piP1 = D0->daughter(2) ; // the second daughter
const LHCb::Particle* piP2 = D0->child(3)    ; // the third daughter
const LHCb::Particle* pim  = D0->particle(4) ; // the fourth daughter
}



Since the results of all these operations are raw C++ pointers to LHCb::Particle= objects, one could effectively reuse the functions & cuts for extraction the useful information:


for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 )
{
const double PKaon = P ( D0(1) ) /GeV ; // Kaon momentum in GeV/c
const double PTpm  = PT( D0(4) )      ; // Momentum of  "pi-"
}



Plenty of methods exist for evaluation of different kinematic quantities of different combinations of daughter particles:


for ( Loop D0 = loop( "K- pi+ pi+ pi-" ) ; D0 ; ++D0 )
{
const LoKi::LorentzVector v   = D0->p()  ; // 4 vector of the whole combination
const LoKi::LorentzVector v0  = D0->p(0) ; // 4 vector of the whole combination
const LoKi::LorentzVector v1  = D0->p(1)    ; // 4-vector of K-
const LoKi::LorentzVector v14 = D0->p(1,4)  ; // 4-vector of K- and pi-
const LoKi::LorentzVector v123 = D0->momentum(1,2,3)  ; // 4-vector of K- and pi+ and pi+
double m12  = D0->p(1,2).m()       ; // mass of K- and the first pi+
double m234 = D0->p(2,3,4).m()     ; // mass of 3 pion sub-combination
doule  m24  = D0->mass(2,4)        ; // mass of 2nd and 4th particles
doule  m13  = D0->m(1,3)            ; // mass of 1st and 3rd particles
}


Alternatively to the convenient short-cut methods Loop::p, Loop::m one could use the equivalent methods Loop::momentum and Loop::mass respectively.

Access to information on the effective mother particle of the combination requires the call of loop method to be supplied with the type of the particle. The information on the particle type can be introduced into the loop in the following different ways:


// particle name
for ( Loop D0 = loop( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 ) { ... }

// particle ID
for ( Loop D0 = loop( "K- pi+ pi+ pi-", 241  ) ; D0 ; ++D0 ) { ... }

// through ParticleProperty object:
const ParticleProperty* pp = ... ;
for ( Loop D0 = loop( "K- pi+ pi+ pi-", pp  ) ; D0 ; ++D0 ) { ... }

// explicit set/reset
Loop D0 = loop( "K- pi+ pi+ pi-" ) ;

D0 -> setPID( 241 )      ;  // set/reset the partcle ID
// the same:
D0 -> setPID( "D0" )     ;  // set/reset the partcle ID
// the same:
D0 -> setPID( pp )       ;  // set/reset the partcle ID

// perform a loop:
for ( ; D0 ; ++D0 )  { ... }



For properly instrumented looping construction one has an access to the information about the effective mother particle of the combination:


for ( Loop D0 = loop ( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 )
{
const LHCb::Particle*   d0_1 = D0   ;
const LHCb::Particle*   d0_2 = D0( 0 )  ;
const LHCb::Particle*   d0_3 = D0->particle()  ;
const LHCb::Particle*   d0_4 = D0->particle( 0 )  ;
const LHCb::Vertex*     v_1  = D0   ;
const LHCb::Vertex*     v_2  = D0->vertex() ;
}



The example above shows several alternative ways for accessing information on "the effective particle" and "the effective vertex" of the combination.

The existence of the implicit conversion of the looping construction to the types const LHCb::Particle* and const LHCb::Vertex* allows to apply all machinery of Particle and Vertex functions and cuts to the looping construction:


for ( Loop D0 = loop( "K- pi+ pi+ pi-", "D0" ) ; D0 ; ++D0 ) {
double mass  = M( D0 ) / GeV ; // mass in GeV
double chi2v = VCHI2( D0 )   ; // chi2 of vertex fit
double pt    = PT ( D0 ) ;  // transverse momentum
}



### Saving of the interesting combinations

Every interesting combination of particles could be saved for future reuse in LoKi and/or DaVinci:


for ( Loop phi = loop( "kaon- kaon+" , "phi(1020)" ) ; phi ; ++phi )
{
if( M( phi )  < 1.050 * Gev ) { phi->save( "phi" ) ; }
}



When particle is saved in internal LoKi storage, it is simultaneously saved into DaVinci's Desktop Tool. For each saved category of particles a new LoKi tag is assigned. In the above example the tag "phi" is assigned to all selected and saved combinations. One could reuse already existing tags to add the n ewly saved particles to existing LoKi containers/selections.

### Usage of kinematic constraints in LoKi

#### Monte Carlo truth matching

LoKi offers fast, easy, flexible and configurable access to Monte Carlo truth information. The helper utility MCMatch could be used to check if given reconstructed particle has the match with given Monte Carlo particle:


MCMatch mcmatch = mcTruth ("My MC-truth matcher") ;

const LHCb::MCParticle* MCD0 = ... ;

for ( Loop D0 = loop( "K- pi+", "D0" ) ; D0 ; ++D0 )
{
if ( mcmatch( D0 , MCD0 ) )  { plot ( M(D0) / GeV , "Mass of true D0 1 " , 1.5 , 2.0 ) ;}
// the same as previous
if ( mcmatch->match( D0 , MCD0 ) )  { plot ( M(D0) / GeV, "Mass of true D0 2 " , 1.5 , 2.0 ) ;}
}



The actual Monte Carlo matching procedure is described in detail here.

MCMatch object could be used for repetitive matching with sequences of arbitrary type of Monte Carlo and reconstructed particles:


// some 'sequence' or 'range' type
typedef std::vector<const LHCb::MCParticle*> MCSEQ   ;
// some 'sequence' or 'range' type
typedef std::vector<const   LHCb::Particle*> RECOSEQ ;

MCSEQ                   mcps = ... ;
RECOSEQ                   ps = ... ;
const LHCb::MCParticle*  mcp = ... ;
const   LHCb::Particle*    p = ... ;

MCMatch mcmatch = mcTruth() ;

/// return the iterator to the first matched RECO particle
RECOSEQ::const_iterator ip =
mcmatch->match( ps.begin () ,   // begin of sequence of Particles
ps.end   () ,   // end   of sequence of Particles
mcp         ) ; // Monte Carlo particle

/// return the iterator to the first  matched MC particle
MCSEQ::const_iterator imcp =
mcmatch->match( p              , // reconstructed particle
mcps.begin ()  , // begin of MC sequence
mcps.end   ()  );// end   of MC sequence

/// return true if *ALL* RECO particles are matched to MC
bool all = mcmatch->
match(   ps.begin   () ,    // begin of sequence of reco particles
ps.end     () ,    // end of sequence o=f reco particles
mcps.begin () ,    // begin of MC sequence
mcps.end   () ) ;  // end   of MC sequence



The methods described above are template, and therefore they could be applied to any type of sequence of pointers to LHCb::MCParticle and LHCb::Particle objects.

Of course in the spirit of LoKi is to provide the same functionality in a more useful and elegant way as ordinary predicate or cut:


const LHCb::MCParticle* MCD0 = ... ;

// create the predicate:
Cut mc = MCTRUTH ( mcTruth() , MCD0 ) ;

for ( Loop D0 = loop( "K- pi+", "D0" ) ; D0 ; ++D0 )
{
// use it!
if ( mc( D0 ) )   { plot ( M(D0) / GeV ,  "mass of true D0" , M(D0)/GeV, 1.5 , 2.0 ) ;}
}


The latter way is especially convenient for analysis.

>
>

## LoKi Reference Manual

#### Revision 22007-07-11 - VanyaBelyaev

Line: 1 to 1

 META TOPICPARENT name="LoKi"

# LoKi User Guide

Changed:
<
<

>
>

### Abstract

LoKi is a package for the simple and user-friendly data analysis.
Changed:
<
<
LoKi is based on Gaudi architechture.
>
>
LoKi is based on Gaudi architecture.
The current functionality of LoKi includes
Changed:
<
<
the selection of particles, manipulaton with predefined kinematical expressions, loops over combinations
>
>
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
Changed:
<
<
with various kinematical constrains and
>
>
with various kinematic constrains and

## User Guide

Line: 24 to 24
digitization, recontruction, vizualization and
Changed:
<
<
analysis, for LHCb~\cite{LHCbTP} collaboration
>
>
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
Changed:
<
<
and its embedded abilities to provide ready-to-use'' nontrivial,
>
>
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.
Line: 39 to 39
of acceptable quality. An essential static nature of the language itself requires the knowledge of compilation and linkage details.
Changed:
<
<
In addition quite often in the typical'' code fragments
>
>
In addition quite often in the "typical" code fragments
for physical analysis the explicit C++ semantics
Changed:
<
<
and syntax hide the physical'' meaning
>
>
and syntax hide the "physical" meaning
of the line and thus obscure the physical analysis algorithm.
Changed:
<
<
Often a simple operation corresponding to one physics'' statement results in an enormouse code with complicated
>
>
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;
Line: 70 to 69
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:
Changed:
<
<
• KAL language (Kinematical Analysis Language) by genius Hartwig Albrecht. KAL is an interpreter language written on
>
>
• 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
Changed:
<
<
and executed by standard KAL executable. The package
>
>
and executed by standard KAL executable. The package
was very successfully used for physics analysis by ARGUS collaboration.
Changed:
<
<
\item {\sc{Pattern}}~\cite{Pattern}\index{{\sc{Pattern}}} and {\sc{GCombiner}}~\cite{GCombiner}\index{{\sc{GCombiner}}} packages by Thorsten Glebe.
>
>
• Pattern and GCombiner packages by Thorsten Glebe.
These nice, powerful and friendly C++ components are used now for
Changed:
<
<
the physics analysis by HERA-B collaboration \item Some obsolete {\sc{Clhep}}~\cite{Clhep}\index{{\sc{Clhep}}} classes, like {\tt{HepChooser}} and {\tt{HepCombiner}} \index{{\sc{Clhep}}!{\tt{HepChooser}}} \index{{\sc{Clhep}}!{\tt{HepCombiner}}} \item {\sc{Loki}}~\cite{Loki}\index{{\sc{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
>
>
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.
Changed:
<
<
\end{itemize}
>
>
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 PROTON  PROTON
IDENT E+      E+
IDENT MU+     MU+

SELECT K- PI+
IF P > 2 THEN
SAVEFITM D0 DMASS 0.045 CHI2 16
ENDIF
ENDSEL

SELECT D0 PI+
PLOT MASS L 2.0 H 2.100 NB 100 TEXT ' Mass of D0 pi+ '
ENDSEL

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

#### 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.

#### Revision 12007-07-11 - VanyaBelyaev

Line: 1 to 1
>
>
 META TOPICPARENT name="LoKi"

# LoKi User Guide

### Abstract

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

## User Guide

### Introduction

All off-line OO software for simulation, digitization, recontruction, vizualization and analysis, for LHCb~\cite{LHCbTP} 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 enormouse 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);
else{
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.
\item {\sc{Pattern}}~\cite{Pattern}\index{{\sc{Pattern}}} and {\sc{GCombiner}}~\cite{GCombiner}\index{{\sc{GCombiner}}} packages by Thorsten Glebe. These nice, powerful and friendly C++ components are used now for the physics analysis by HERA-B collaboration \item Some obsolete {\sc{Clhep}}~\cite{Clhep}\index{{\sc{Clhep}}} classes, like {\tt{HepChooser}} and {\tt{HepCombiner}} \index{{\sc{Clhep}}!{\tt{HepChooser}}} \index{{\sc{Clhep}}!{\tt{HepCombiner}}} \item {\sc{Loki}}~\cite{Loki}\index{{\sc{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. \end{itemize}

-- Main.ibelyaev - 11 Jul 2007

Copyright &© 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