LoKi F.A.Q.

This page will be populated with Frequently Asked Questions concerning LoKi.

Add your own Question

Did you not find the answer you were looking for? If not please submit your question here.

Current user-submitted FAQ's can be found here

What/Who is LoKi

  • LoKi is C++ ToolKit for Smart and Simple Physics Analysis. All available documentation is linked from the LoKi pages and/or LoKi portal
  • Loki is a god of wit and mischief in Norse mythology
  • LoKi could be interpreted as Loops&Kinematics

Where could I find the proper documentation?

What LoKi functors are recommended for usage withing CombineParticles/FilterDesktop framework?

The list LoKi functors which are recommended for usage withing CombineParticles/FilterDesktop framework can be inspected here.

How to use MC-truth matching inside CombineParticles/FilterDesktop framework?

The usage of MC-truth inside CombineParticles/FilterDesktop framwork is fairly trivial, e.g.

 1000MyAlg = CombineParticles ( ... ... DaughterCuts = { 'K+' : " ( PT > 1 * GeV ) & mcMatch ( ' phi(1020) => ^K+ ^K-' ) " , 'mu+' : " (PT > 1 * GeV) & mcMatch ( 'J/psi(1S) => ^mu+ ^mu-' ) " } ,
 1010
 1020Preambulo = [ "from LoKiPhysMC.decorators import *" , "from LoKiPhysMC.functions import mcMatch" ]
 1030
 1040)

For the exampe above , only the recontructed kaons, matched with true MC-kaons from decays of , and the recontructed muons, matched with true MC-muons form the decay will be selected. (Note: The indefinite amount of soft photons from the internal bremstrahlung, produced by PHOTOS generator is allowed. For more detaild about the decay descripor see here)

The "selector" of MC-particles (the first argument of mcMatch function) can be defined in many different ways:

  • it can be string decay descriptor, see here and here
  • it can be tree or node object, see here
  • it can be predicate acting on Monte Carlo particles
For the actual details of MC-truth matching algorithm in LoKi please consult LoKi User Guide The defaulmatching is done using the protoparticles. To customize the MC-matching one can specif the TES-locations of relation tables as helper arguments of mcMatch functions. The following relation table typoes are supported ( see $LOKIPHYSMCROOT/LoKi/PhysMCTypes.h file):
  • LoKi::Types::TableP2MC
  • LoKi::Types::TableP2MCW
  • LoKi::Types::TablePP2MC
  • LoKi::Types::TableT2MC
  • LoKi::Types::TableT2MCW

More detailed example is available here

How to study the background composition with LoKi?

LoKi offers many suitabel ways to study the background compostion. One of the most powerful tool is algorithm LoKi::DecayTruth (known as LoKiDecayTruth in DC04 branch of software). The algorithm has been adapted to DC06 software line by Lesya SHCHUTSKA. The algorithm has been adapted to DC06 software line by Lesya SHCHUTSKA.

LoKi::DecayTruth algorithm

This algorithm allows to study the MC-truth for the selected signal candidates through rather intensive printout. For the channels with no photons, one can inspect up to O(50) events, while for channels with photons the inspection of more than 20 events is rather painful. The usage of the algorithm is rather trivial, one just need to specify the TES location with the selected signal candidates and the list of "interesting" PIDs:

// add the algorithm into the list of top-level algorithm for Gaudi: ApplicationMgr.TopAlg += { "LoKi::DecayTruth/MCTruth" } ;

// define the location of signal candidates: MCTruth.Desktop.InputLocations = { "Phys/MySignalBCandidates" } ;

// define the "interesting" PIDs: MCTruth.Particles = { "B_s0" , "B_s~0"} ;

If the decay channel under the interest does not contain photons, to speedup the program a bit one can disable the MC-mathching for the photons:

// OPTIONALLY, if decay does not contains PHOTONS: MCTruth.PP2MCPs = { "Relations/Rec/ProtoP/Charged" };

The algorithm is rather simple. E.g. for the selected candidates -candidates from the file which contains followed by , algorithm prints the information about all recontructed -candidates (in our case only one candidate is found):

MCTruth           SUCCESS  Reconstructed B_s0  #1/1 (key:4)
 0 |->B_s0                                     E/PX/PY/PZ:  107.7  /  4.726  /  -6.533 /  107.3   [GeV]  #  4
 1    |->J/psi(1S)                             E/PX/PY/PZ:  58.19  /  1.094  /  -3.776 /  57.97   [GeV]  #  0
 2       |->mu+                                E/PX/PY/PZ:  46.18  /  1.057  /  -4.239 /  45.97   [GeV]  #  1
 2       |->mu-                                E/PX/PY/PZ:    12   / 0.01673 /  0.4615 /  11.99   [GeV]  #  0
 1    |->phi(1020)                             E/PX/PY/PZ:  49.52  /  3.632  /  -2.749 /   49.3   [GeV]  #  1
 2       |->K+                                 E/PX/PY/PZ:  20.08  /   1.49  /  -1.17  /  19.98   [GeV]  #  0
 2       |->K-                                 E/PX/PY/PZ:  29.43  /  2.141  /  -1.579 /   29.3   [GeV]  #  1

Than, for each reconstructed particle in the decay tree (including the -candidate as "the head" of the tree, it try to find the Monte Carlo particles which makes the direct or indirect contribution to this reconstructed particle. The algorithm prints the overall number of such Monte Carlo Paerticles, as well as the total number of independent Monte Carlo trees, whcih makes the contribution. And each independent Monte Carlo tree is printed, and the tree components, which make the direct or indirect contribution are "marked" with an asterisk in the first position. E.g. fot the recontructed negative kaon, one finds three Monte Carlo particles, which comes from only one independent Monte Carlo tree:

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'K-' 7/7 (key:0):  #'matched' MC trees 1 (#'matched' MC particles 3)
*0 |->B_s0                         E/PX/PY/PZ:  70.01  /  -1.844 /  -8.547 /  69.25   [GeV]  #2338
*1    |->phi(1020)                 E/PX/PY/PZ:  27.63  /  0.8406 /  -3.374 /  27.39   [GeV]  #2339
*2       |->K-                     E/PX/PY/PZ:  17.15  /  0.5602 /  -2.154 /    17    [GeV]  #2340
 2       |->K+                     E/PX/PY/PZ:  10.48  /  0.2804 /  -1.22  /  10.39   [GeV]  #2341
 1    |->J/psi(1S)                 E/PX/PY/PZ:  42.38  /  -2.685 /  -5.173 /  41.86   [GeV]  #2342
 2       |->mu-                    E/PX/PY/PZ:  35.45  /  -2.758 /  -5.342 /  34.93   [GeV]  #2343
 2       |->mu+                    E/PX/PY/PZ:  6.934  / 0.07358 /  0.1693 /   6.93   [GeV]  #2344

One clearly see that this reconstructed Kaon comes from true Monte Carlo kaon from the true Monte Carlo decay followed by ,. And one see that three Monte Calro particles ( with the key 2340, with the key 2339 and with the key 2338) make the contribution to this reconstructed kaon. In a similar way the MC-mathching information for all other particles from the reconstructed -candidate is printed:

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'B_s0' 1/7 (key:4):  #'matched' MC trees 1 (#'matched' MC particles 1)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
 1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
 1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'J/psi(1S)' 2/7 (key:0):  #'matched' MC trees 1 (#'matched' MC particles 2)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
 1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
*1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'mu+' 3/7 (key:1):  #'matched' MC trees 1 (#'matched' MC particles 3)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
 1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
*1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
*2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'mu-' 4/7 (key:0):  #'matched' MC trees 1 (#'matched' MC particles 3)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
 1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
*1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
*2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'phi(1020)' 5/7 (key:1):  #'matched' MC trees 1 (#'matched' MC particles 2)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
*1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
 1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'K+' 6/7 (key:0):  #'matched' MC trees 1 (#'matched' MC particles 3)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
*1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
 2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
*2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
 1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

MCTruth           SUCCESS  Inspect reconstructed daughter particle  'K-' 7/7 (key:1):  #'matched' MC trees 1 (#'matched' MC particles 3)
*0 |->B_s0                         E/PX/PY/PZ:  107.5  /  4.726  /  -6.507 /  107.1   [GeV]  #2271
*1    |->phi(1020)                 E/PX/PY/PZ:  49.66  /   3.64  /  -2.761 /  49.44   [GeV]  #2272
*2       |->K-                     E/PX/PY/PZ:   29.7  /  2.164  /  -1.595 /  29.57   [GeV]  #2273
 2       |->K+                     E/PX/PY/PZ:  19.96  /  1.476  /  -1.165 /  19.87   [GeV]  #2274
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2275
 4             |->pi+              E/PX/PY/PZ:  0.6881 /  0.3765 / -0.03625/  0.5576  [GeV]  #2276
 3          |->Intermediate        E/PX/PY/PZ:    0    /    0    /    0    /    0     [GeV]  #2277
 4             |->e+               E/PX/PY/PZ:  0.2595 / 0.04696 / -0.2055 /  0.1514  [GeV]  #2278
 1    |->J/psi(1S)                 E/PX/PY/PZ:  57.83  /  1.086  /  -3.746 /  57.62   [GeV]  #2279
 2       |->mu-                    E/PX/PY/PZ:  12.04  / 0.03374 /  0.4577 /  12.03   [GeV]  #2280
 2       |->mu+                    E/PX/PY/PZ:   45.8  /  1.052  /  -4.204 /  45.59   [GeV]  #2281

On Linux platform, the lines marked by asterisk in the first column also are colored, making the analysis of these tables much easier: snap.jpg

If one needs some information about the vertices, one can configure the algorithm properly:

RCVertex
Print the information about the vertices (if available) for the recontructed particles
MCVertex
Print the information about the origin-vertices for the Monte Carlo particles
MCVertexE
If the previous flag activated, it allows to print the information about the end-vertices for Monte Carlo particles
MCVertexD
If activated flag activated, only Monte Carlo particles from decay tree will be considered. All Monte Carlo particles from the secondary intteractions in the detector will be ignored

How to use the various "decay-finders" in LoKi?

There are few ways to find the certain decay patterns in LoKi:

  1. The brilliant (MC)DecayFinder tools, written by Olivier Dormond and few functors based on them
  2. New "tree/node" utilities, which allow to describe/construct the decay descriptions of the arbitrary complexity
  3. New (re)-implementation of "decay-finder"-tools by Alexander Mazurov, based on "tree/node" utilities

Some examples are available here and here.

How to "monitor" various LoKi functors, used in CombineParticles/FilterDesktop framework?

There are few basic monitoring tool:

  1. Simple printout to std::cout, useful for simple debugging & fast checks
  2. Histograms
  3. Counters

Monitoring using the printout to std::cout

To perform the printout of functor value one just needs to "decorate" the functor using the helper function monitor:

 1000# monitor the functor M 
 1010MyAlg.XXXCut = "monitor( M ) > 1000"
 1020
 1030# monitor the predicate M > 1000 
 1040MyAlg.XXXCut = "monitor( M > 1000 )"
 1050
 1060# monitor everything 
 1070MyAlg.XXXCut = "monitor( monitor( M ) > 1000 )"

Clearly this mointoring is not acceptable for any offiical code and shodul be used only for private checks & debugging

Monitoring using the automatically booked histograms

Here again the function monitor is in the game:

 1000# monitor the functor M using 'local' histogram of GaudiHistoAlg, available through IAlgContextSvc 
 1010MyAlg.XXXCut = "monitor( M , Gaudi.Histo1DDef( 'histo title', 0 , 5000) , 'histoID' ) > 1000"
 1020
 1030# monitor the functor M using 'global' histogram, booked directly through IHistogramSvc 
 1040MyAlg.XXXCut = "monitor( M , 'histo/directory', 'histoID' , Gaudi.Histo1DDef( 'histo title', 0 , 5000) ) > 1000"

To avoid the overcomplication of the lines, one can predefine the histograms using the property Preambulo:

 1000MyAlg.Preambulo += [ 
 1010    "h1 = Gaudi.Histo1DDef( 'histo title 1 ', 0 , 5000 , 100 )" , 
 1020    "h2 = Gaudi.Histo1DDef( 'histo title 2 ' , 0 , 5000 , 100 )", 
 1030] 
 1040
 1050# monitor the functor M using 'local' histogram of GaudiHistoAlg, available through IAlgContextSvc 
 1060MyAlg.XXXCut = "monitor( M , h1 , 'histoID' ) > 1000"
 1070
 1080# monitor the functor M using 'global' histogram, booked directly through IHistogramSvc 
 1090MyAlg.XXXCut = "monitor( M , 'histo/directory', 'histoID' , h2 ) > 1000"

Also the histograms can be predefined using the property Lines for the corresponding Python/Hybrid factory.

Please note, that thistogramming is available only for functions, the predicates can't be monitored in this way.

Monitoring using the explicitly booked histograms

The histograms can be booked also expliclitly using IHistogramDataSvc and utilities from GaudiPython.HistoUtils module

 1000MyAlg.Preambulo += [ 
 1010    "from GaudiPython.HistoUtils import book " ,   # import helper function 
 1020    "histo = book('/stat/this/is/a/path/in/histogram/data/store', 'ID' , 'title' , 100 , 0 , 10000 )",  # book the histogram 
 1030]

And finally one canuse the booked histogram for monitoring:

 1000# monitor the functor M using explicitly booked histogram: 
 1010MyAlg.XXXCut = "monitor( M , histo ) > 1000"

Monitoring using the automatically booked counters

The functors (both functions & predicates) can be monitored using the counters, see StatEntity class.

The counters can be "local" (managed by the corresponding GaudiAlgorithm class, or "global" (managed by IStatSvc or ICounterSvc).

 1000# monitor the functor M using 'local' counter of corresponding GaudiAlgorithm 
 1010MyAlg.XXXCut = "monitor( M , 'mass' , LoKi.Monitoring.IContextSvc ) > 1000 "
 1020
 1030# monitor the functor M using 'global' counter of IStatSvc 
 1040MyAlg.XXXCut = "monitor( M , 'mass' , LoKi.Monitoring.IStatSvc ) > 1000"
 1050
 1060# monitor the functor M using 'global' counter of ICounterSvc 
 1070MyAlg.XXXCut = "monitor( M , 'mass' , LoKi.Monitoring.ICounterSvc ) > 1000"
 1080
 1090# monitor the functor M using 'global' counter of ICounterSvc 
 1100MyAlg.XXXCut = "monitor( M , 'group' , 'mass' , LoKi.Monitoring.ICounterSvc ) > 1000"

(Instead of long enums LoKi.Monitoring.IContextSvc/IStatSvc/ICounterSvc one can use their short numerical values: 0, 1 and 2 correspondingly). Please note that for monitoring of predicates it is advisable to ensure the counter name contains one of the following case-insensitive substrings: eff, acc,filt,fltr, pass, see here. For these cases the special printout format is activated, suitable for monitoring of boolean values..

Advanced monitoring using VoidFilter and streamers

There is nice utility for monitoring using so called LoKi::VoidFilter. Thus technique is applicable to any objects, eg. tracks, vertices, (mc)particles, etc, and it allows to monitor also quantities like "maximal transverse momentum" or even "momentum of the particle with maximal transverse momentum". The idea is based on the genious idea of streamers by Gerhard The Great. The stremers represent the overall data flow, and using the helper functions the dat aflow can be modifies, and controlled. Finally for usage with VoidFilter one need to construct th eobject with the signature void->bool, The simplest example is:

 1000from Configurables import LoKi__VoidFilter as MonFilter
 1010
 1020moni = MonFilter( 'I_am_Monitor', Code = "SOURCE('HLT/Hlt2Muons') >> ~EMPTY" )

And a top of the functors , one can add monitoring:

 1000from Configurables import LoKi__VoidFilter as MonFilter
 1010
 1020moni = MonFilter( 'I_am_Monitor' )
 1030
 1040# 0. filter good container
 1050moni.Code = " SOURCE('HLT/Hlt2Muons') >> SIZE > -1"
 1060    
 1070# 1. printout
 1080## a. print PT for all particles 
 1090moni.Code = "SOURCE('HLT/Hlt2Muons') >> ( monitor(PT) > 100 ) >> ( SIZE > -1 )"
 1100## b. print PT for all particles 
 1110moni.Code = "SOURCE('HLT/Hlt2Muons') >> process(monitor( PT )) >> ( SIZE > -1 )"
 1120## c. print max(PT) 
 1130moni.Code = "SOURCE('HLT/Hlt2Muons') >> tee(monitor(max_value( PT ))) >> ( SIZE > -1 ) "
 1140
 1150# 2. histograms 
 1160## a. plot PT for all particles 
 1170moni.Code = """
 1180SOURCE('HLT/Hlt2Muons')
 1190>> process( monitor( PT ) > 100 )  
 1200    >> tee ( monitor( max_value ( PT ) ) > 100 )  
 1210    >> tee ( monitor( min_value ( PT ) ) > 100 )
 1220>> process( monitor( PT , 'pt' , LoKi.Monitoring.StatSvc ) > 100 )  
 1230    >> tee ( monitor( max_value ( PT ), 'maxpt', LoKi.Monitoring.StatSvc ) > 100 )  
 1240    >> tee ( monitor( min_value ( PT ), 'minpt', LoKi.Monitoring.StatSvc ) > 100 )
 1250>> process( monitor( PT , histo1 ) > 100 )  
 1260    >> tee ( monitor( max_value ( PT ), histo2 ) > 100 )  
 1270    >> tee ( monitor( min_value ( PT ), histo3 ) > 100 )
 1280>> process( monitor( PT , '/stat/Moni/h1', h1 ) > 100 )  
 1290    >> tee ( monitor( max_value ( PT ), '/stat/Moni/h2', h2 ) > 100 )  
 1300    >> tee ( monitor( min_value ( PT ), '/stat/Moni/h3', h3 ) > 100 )
 1310>> process( monitor( PT , h1 , 'localH1' ) > 100 )  
 1320    >> tee ( monitor( max_value ( PT ), h2 , 'localH2' ) > 100 )  
 1330    >> tee ( monitor( min_value ( PT ), h3 , 'localH3' ) > 100 )
 1340>> ( SIZE > -1 ) 
 1350"""
 1360
 1370moni.Preambulo = """
 1380from LoKiCore.functions import *
 1390from LoKiPhys.decorators import *
 1400from GaudiPython.HistoUtils import book
 1410histo1 = book( '/stat/filter/PT', 'pt1'  , 'title: PT'   , 100, 0.0, 10000.0) 
 1420histo2 = book( '/stat/filter/PT', 'ptmax', 'title: PTMAX', 100, 0.0, 10000.0) 
 1430histo3 = book( '/stat/filter/PT', 'ptmin', 'title: PTMIN', 100, 0.0, 10000.0)
 1440h1 = Gaudi.Histo1DDef('my PT-histo'   , 0, 10000)
 1450h2 = Gaudi.Histo1DDef('my PTMAX-histo', 0, 10000)
 1460h3 = Gaudi.Histo1DDef('my PTMIN-histo', 0, 10000)
 1470""".split('\n')
 1480

Helper streamer functions

  • process , accept container, apply the functor to each element of container and return the initial container (unmodified)
  • tee, accept container, branch the data flow, and return the initial container (unmodified)
  • min_value, accept the container and return the minimal value of certain functor
  • max_value, accept the container and return the maximal value of certain functor
  • min_abs_value, accept the container and return the abs-minimal value of certain functor
  • max_abs_value, accept the container and return the abs-maximal value of certain functor
  • min_element, accept the container, and return element which minimizes the certain functor
  • max_element, accept the container, and return element which maximizes the certain functor
  • min_abs_element, accept the container, and return element which abs-minimizes the certain functor
  • max_abs_element, accept the container, and return element which abs-maximizes the certain functor
  • yields, accept container and return the container with values of certain functor
  • has, accept container and check the scalar predicate
  • count, accept container and count the sing the scalar predicate
  • select, accept container and select the elemenets which satisfy the scalar predicate
Note that often one can avout the explicit appearence of control functions, e..g the follwoing expressions are equivalent:

 1000MyAlg.Code = "SOURCE('HLT/Hlt2Muons', PT > 1000 ) >> ~EMPTY "
 1010
 1020MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> select( PT > 1000 ) >> ~EMPTY "
 1030
 1040MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> ( PT > 1000 ) >> ~EMPTY "
 1050
 1060MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> count( PT > 1000 ) != 0 "
 1070
 1080MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> yields( PT ) >> count( X > 1000 ) != 0 "
 1090
 1100MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> yields( PT ) >> ( X > 1000 ) >> ~XEMPTY "
 1110
 1120MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> yields( PT ) >> select( X > 1000 ) >> ~XEMPTY "
 1130
 1140MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> PT >> count( X > 1000 ) != 0 "
 1150
 1160MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> PT >> ( X > 1000 ) >> ~XEMPTY "
 1170
 1180MyAlg.Code = "SOURCE('HLT/Hlt2Muons') >> PT >> select( X > 1000 ) >> ~XEMPTY "

Monitoring using "fake" functors

One also can perform moniring using "fake" functors, e.g.

 1000# monitor the functor M using 'local' counter of corresponding GaudiAlgorithm 
 1010MyAlg.XXXCut = "PT > 1000"
 1020
 1030# redefine the meaning of PT ! 
 1040MyAlg.Preambulo = [ "PT = monitor( PT , ... ) " ]

Examples

All monitoring utilities listed above are illustrated for the following code fragment (using Hlt2 framework and FilterDesktop algorithm:

 1000algo = Hlt2Member( FilterDesktop , "Filter" , InputLocations = [Muons] )
 1010
 1020# 0. Original `Code` snippet. Can be replaces by examples below
 1030algo.Code = "PT > 2.8*GeV" 
 1040
 1050# 1. use std::cout 
 1060## a. monitor the function 
 1070Code = "monitor(PT) > 2.8*GeV" 
 1080## b. monitor the predicate 
 1090Code = "monitor(PT > 2.8*GeV)" 
 1100
 1110# 2. use "local" counters 
 1120## a. monitor the function 
 1130Code = "monitor(PT, 'PT-counter', LoKi.Monitoring.ContextSvc) > 2.8*GeV" 
 1140## b. monitor the predicate 
 1150Code = "monitor(PT > 2.8*GeV, 'PT-cut-eff', LoKi.Monitoring.ContextSvc)" 
 1160
 1170# 3. use "global" counters: StatSvc 
 1180## a. monitor the function 
 1190Code = "monitor(PT, 'PT-counter', LoKi.Monitoring.StatSvc) > 2.8*GeV" 
 1200## b. monitor the predicate 
 1210Code = "monitor(PT > 2.8*GeV, 'PT-cut-eff', LoKi.Monitoring.StatSvc)" 
 1220
 1230# 4. use "global" counters: CounterSvc 
 1240## a. monitor the function 
 1250Code = "monitor(PT, 'PT-counter', LoKi.Monitoring.CounterSvc) > 2.8*GeV" 
 1260## b. monitor the predicate 
 1270Code = "monitor(PT > 2.8*GeV, 'PT-cut-eff', LoKi.Monitoring.CounterSvc)" 
 1280
 1290# 5. use "global" counters with 'Group'-attribute CounterSvc 
 1300## a. monitor the function 
 1310Code = "monitor(PT, 'MUON', 'PT-counter', LoKi.Monitoring.CounterSvc) > 2.8*GeV" 
 1320## b. monitor the predicate 
 1330Code = "monitor(PT > 2.8*GeV, 'MUON', 'PT-cut-eff', LoKi.Monitoring.CounterSvc)" 
 1340
 1350# 6. Use local histograms [check that historamming is not disabled!!!] 
 1360## a. monitor the function, literal ID 
 1370Code = "monitor(PT, h1, 'my-histo') > 2.8*GeV" 
 1380## a. monitor the function, numerical ID 
 1390Code = "monitor(PT, h1, 10) > 2.8*GeV" 
 1400
 1410# 7. Use global histograms: 
 1420# a. monitor the function, full path in HDS 
 1430Code = "monitor(PT, '/stat/MUONS/pt', h1) > 2.8*GeV"
 1440# b. monitor the function, full path in HDS + literal ID 
 1450Code = "monitor(PT, '/stat/MUONS/pt', 'Pt', h1) > 2.8*GeV"
 1460## c. monitor the function, full path in HDS + integer ID 
 1470Code = "monitor(PT, '/stat/MUONS/pt', 15, h1) > 2.8*GeV"
 1480 
 1490# 8. use prebooked histograms 
 1500## a. monitor the function 
 1510algo.Code = "monitor(PT,histo) > 2.8*GeV" 
 1520algo.HistoProduce = True
 1530algo.Preambulo = """
 1540# needed for groups 6 & 7 
 1550h1 = Gaudi.Histo1DDef('my PT-histo', 0, 10000)
 1560# definition of the histogram parameters, 
 1570# needed from group 8 
 1580from GaudiPython.HistoUtils import book
 1590histo = book( '/stat/path_in_HTS/MUON/pt', 'ID', 'title', 100, 0.0, 10000.0 )
 1600""".split('\n')
 1610

Another example is available here

An example, monitoring the LoKi filters in the Hlt2InclusivePhi alley.

How to code own LoKi functor?

From pure formal point of view the implementation of own LoKi functors is just a trivial task. In short one shoudl follow the instructions from here or here.

In a nutshell

Each LoKi functor inherits from the base class LoKi::Functor, where TYPE1 defines the (single) argument type and TYPE2 defines the return value. The formal actual argument type (which in general is different from TYPE1 is provided by the typedef argument, and the actual type of result is defined as result_type.

According to the type of TYPE2 all existing LoKi functors can be classified as:

  • function: TYPE2=double
  • predicate: TYPE2=bool
  • streamers: TYPE2=std::vector< TYPE3 > for some TYPE3
According to the type of TYPE1 all existing LoKi functors can be classified as:
  • particle functors : TYPE1=const LHCb::Particle*
  • vertex functors : TYPE1=const LHCb::VertexBase*
  • Monte Carlo particle functors : TYPE1=const LHCb::MCParticle*
  • Monte Carlo vertex functors : TYPE1=const LHCb::MCVertex*
  • Generator particle functors : TYPE1=const HepMC::GenParticle*
  • Generator vertex functors : TYPE1=const HepMC::GenVertex*
  • Array particle functors : TYPE1=LoKi::Range_
  • track functors : TYPE1=LHCb::Track
  • rec-vertex functors : TYPE1=LHCb::RecVertex
  • track-track bi-functors: TYPE1=LoKi::TrackTypes::TrackPair
  • track-rec-vertex bi-functors: TYPE1=LoKi::TrackTypes::TrackVertexPair
  • rec-vertex-rec-vertex bi-functors: TYPE1=LoKi::TrackTypes::VertexPair
  • streamers : TYPE1=std::vector< TYPE3 > for some TYPE3
  • numbers : TYPE1=double
If new functor falls into one of the category, the subsequent decoration for interactive usage in Python,Bender or CombineParticles is trivial and automatic. Otherwise the decoration is not a trivial task, please contact me in this case and we'll try to find the appropriate solution.

The coding is especially simple for the certain combinations of TYPE1 and TYPE2 , whcih are available through LoKi::BasicFunctors template, which defines the reasonable functor signatures for various purposes.

Function
LoKi::Functor
Predicate
LoKi::Functor
Map
LoKi::Functor,std::vector< double > >
Pipe
LoKi::Functor,std::vector< TYPE > >
FunVal
LoKi::Functor , double>
CutVal
LoKi::Functor,bool>
Element
LoKi::Functor,TYPE>
Source
LoKi::Functor >

Choose the base

Lets start wit very simple functor, e.g. transverse momentum of particle. Clearly here both TYPE1 and TYPE2 are well defined: TYPE1=const LHCb::Particle* and TYPE2=double, and the functor signature corresponds to LoKi::BasicFunctors::Function:

 1000class MyFunctor : public LoKi::BasicFuctors<const LHCb::Particle>::Function { ... } ;

To simplify the subsequent generation of Reflex dictionaries, it is highly recommended to put the functor into some namespace:

 1000namespace LoKi {
 1010
 1020namespace XXX {
 1030
 1040class MyFunctor : ... } // end of namespace LoKi::XXX
 1050
 1060} // end of namespace LoKi
 1070

Mandatory methods

Each funtor must implement three mandatory methods:

  • virtual destructor: virtual ~MyFunctor()
  • cloning: virtual MyFunctor* clone() const
  • virtual result_type operator()( argument a ) const
 1000class MyFunctor : public LoKi::BasicFuctors<const LHCb::Particle>::Function {
 1010
 1020public:
 1030
 1040// MANDATORY: virtual destructor:
 1050
 1060virtual ~MyFunctor();
 1070
 1080// MANDATORY: clone method ("virtual constructor")
 1090
 1100virtual MyFunctor* clone() const ;
 1110
 1120// MANDATORY: the only one essential method
 1130
 1140virtual result_type operator () ( argument a ) const ;
 1150
 1160} ;

Please note the usage of result_type and argument.

The typical implementation of destructor and clone mehtod applicable for almost all cases is

 1000// destructor: 
 1010LoKi::XXX::MyFunctor::~MyFunctor(){};
 1020
 1030// clone method ("virtual constructor") 
 1040LoKi::XXX::MyFunctor* LoKi::XXX::MyFunctor::clone() const { return new LoKi::XXX::MyFunctor(*this); }

The implementation of the major method could be e.g.

 1000// the major method LoKi::XXX::MyFunctor::result_type LoKi::XXX::MyFunctor::operator() ( LoKi::XXX::MyFunctor::argument a ) const {
 1010
 1020// check the argument: if ( 0 == a ) { Error ("Invalid argument, return 'InvalidMomentum'") ; return LoKi::Constants::InvalidMomentum ; }
 1030
 1040// calculate the result:
 1050
 1060double result = a -&gt; pt() ;
 1070
 1080return result ; }

Please note again the usage of result_type and argument. Also note the usage of helper member-function Error from base class LoKi::AuxFunBase.

This minimal setup is already enough touse the function in C++, e.g. with bare LoKi:

 1000// make the instance:
 1010
 1020const LoKi::XXX::MyFunctor fun = LoKi::XXX::MyFunctor() ;
 1030
 1040// get the particle
 1050
 1060const LHCb::Particle* B = ... ;
 1070
 1080// use the functor:
 1090
 1100const double result = fun ( B ) ;

Optional method

One can redefine the self-printout of the functor:

 1000namespace LoKi { namespace XXX { class MyFunctor : public LoKi::BasicFuctors<const LHCb::Particle>::Function {
 1010
 1020public: ... /// OPTIONAL: nice printout virtual std::ostream& fillStream( std::ostream& s ) const ; ... } ; } } 
 1030

The typical implementation is

 1000std::ostream& LoKi::XXX::MyFunctor::fillStream ( std::ostream& ) const { return s &lt;&lt; "MYFUN" ; }

It is convinient to define proper type inside the the namespace LoKi::Cuts to be in agreement with self-printout:

 1000namespace LoKi { namespace Cuts { /** @var MYFUN * put some reasonable comment here and example of the code * @code * ... * @endcode * @see LoKi::XXX::MyFunctor * @date 2009-04-07 * @author Xxx Yyyy ZZZ@aaa.bbb */ const LoKi::XXX::MyFunctor MYFUN ; } } 

For this case one can use in C++ a bit simple expressions:

 1000// get the particle
 1010
 1020const LHCb::Particle* B = ... ;
 1030
 1040// use the functor:
 1050
 1060const double result = MYFUN ( B ) ;

Generating Reflex dictionaries

To produce Reflex dictionaries it is enough to include (directly or indirectly) the corresponding header file into corresponding $LOKIXXXROOT/dict/LoKiXXXDict.h file and to ensure that the corresponding $LOKIXXXROOT/dict/LoKiXXX.xml file contains the line:

 1000<class name="LoKi::XXX::MyFunctor"  />

XXX shodul be defined as the most appropriate location, e.g. here it could be the package Phys/LoKiPhys.

Python decoration

To activate the useful functionality in python one needs to perform the proper decoration. The standard decoration is activated automatically if one declares the objects inside corresponding $LOKIXXXROOT/python/LoKiXXX/functions.py file:

 1000## @see LoKi::Cuts::MYFUN MYFUN = LoKi.XXX.MyFunctor ()
 1010

From here the functor is "ready" and one can use it both in C++ (LoKi) and Python (Bender) and CombineParticles framework in a coherent way:

 1000from Configurables import CombineParticles
 1010
 1020myAlgorithm = CombineParticles ( .... )
 1030
 1040myAlgorithm.MotherCuts = " MYFUN &gt; 1000 "

What to do if functor has no default constructor?

For the functors whithout defautl constructor, of fro functors which require to be configured during the instantiation, the described procedure need to be modified, since we can neither define the instances in LoKi::Cuts namespace nor in $LOKIXXXROOT/python/LoKiXXX/functions.py module.

For this case instead of instances one needs to defien the types:

 1000namespace LoKi { namespace Cuts { /** @typedef MYFUN2 * put some reasonable comment here and example of the code * @code * ... * @endcode * @see LoKi::XXX::MyFunctor2 * @date 2009-04-07 * @author Xxx Yyyy ZZZ@aaa.bbb */ typedef LoKi::XXX::MyFunctor2 MYFUN2 ; } } 

And

 1000## @see LoKi::Cuts::MYFUN2 MYFUN2 = LoKi.XXX.MyFunctor2
 1010

The usage of symbols in this case is:

 1000from Configurables import CombineParticles
 1010
 1020myAlgorithm = CombineParticles ( .... )
 1030
 1040myAlgorithm.MotherCuts = " MYFUN2 ( ... the constructor arguments are here ... ) &gt; 1000 "

How to evaluate various polarization angles?

There are few basic functors for evaluation of polarizaton angles.

Polarization of particles in laboratory frame

For evaluation of polarization angles in laboratory frame one can use the functor LV0 (the type)

LV01
evaluates the cosine of the angle of between the momentum direction of the first daughter particle in the rest frame of the mother particle with respect to the direction of the boost form the laboratory frame to the rest-frame of mother particle
LV02
evaluates the cosine of the angle of between the momentum direction of the second daughter particle in the rest frame of the mother particle with respect to the direction of the boost form the laboratory frame to the rest-frame of mother particle
LV03
evaluates the cosine of the angle of between the momentum direction of the third daughter particle in the rest frame of the mother particle with respect to the direction of the boost form the laboratory frame to the rest-frame of mother particle
LV04
evaluates the cosine of the angle of between the momentum direction of the fourth daughter particle in the rest frame of the mother particle with respect to the direction of the boost form the laboratory frame to the rest-frame of mother particle

C++ example

 1000// get the particle const LHCb::Particle* particle = .... ;
 1010
 1020// get the cosine of decay angle const double cosTheta = LV01( particle ) ;
 1030

Python example

 1000## get the particle particle = ...
 1010
 1020## get the cosine of decay angle cosTheta = LV01( particle )
 1030

LoKi::Hybrid::TupleTool example

 1000## add the variable myTool.Variables = {
 1010
 1020'cosTheta' : "LV01"
 1030
 1040}

Polarization of daughter particles in the frame of mother particles

The functor COSPOL ( MCCOSPOL for Monte Carlo particles, GENCOSPOL for generator/HepMC particles) allows to evaluate the cosine of the angle between the momentum direction of one of the particle in the decya tree, in the rest frame of another particle in the decay tree with respect the direction of the boost from the head of the decay frame to the rest-frame of the second particle. E.g. it can be used for evaluation of

  • / for such decays as , , ;
  • for decays , , , ;
  • for decays , etc..
To use this functors one needs to specify children particles, used for evaluation of angles, e.g.

C++

 1000// create the functors const COSPOL cosTheta_K = COSPOL ( "B0 --&gt; ( K*(892)0 -&gt; ^K- \pi^+ ) ( J/psi(1S) \to \mu+ \mu- ) ", "B0 --&gt; ^( K*(892)0 -&gt; K- \pi^+ ) ( J/psi(1S) \to \mu+ -\mu- ) " ) ; const COSPOL cosTheta_L = COSPOL ( "B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ( J/psi(1S) \to ^\mu+ \mu- ) ","B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ^( J/psi(1S) \to \mu+ -\mu- ) '") ;
 1010
 1020// get B-candidate const LHCb::Particle* B = ... ;
 1030
 1040// use the functor const double value_K = cosTheta_K ( B ) ; const double value_L = cosTheta_L ( B ) ;
 1050

Python:

 1000## create the functors cosTheta_K = COSPOL ( 'B0 --&gt; ( K*(892)0 -&gt; ^K- \pi^+ ) ( J/psi(1S) \to \mu+ \mu- ) ', 'B0 --&gt; ^( K*(892)0 -&gt; K- \pi^+ ) ( J/psi(1S) \to \mu+ -\mu- ) ' ) cosTheta_L = COSPOL ( 'B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ( J/psi(1S) \to ^\mu+ \mu- ) ', 'B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ^( J/psi(1S) \to \mu+ -\mu- ) ' )
 1010
 1020## get B-candidate B = ...
 1030
 1040## use the functor value_K = cosTheta_K ( B ) value_L = cosTheta_L ( B )
 1050

For some cases, e.g. for evaluation of for decay , oen can't speify the intermediate particle "dimuon", in this case one should specify the optional parameter, to indicate that effective "dimuon" is effectively constructed ftom the first and the second specified arguments:

C++:

 1000// create the functors const double COSPOL cosTheta_L = COSPOL ( "B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ^\mu+ \mu- ", "B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) \mu+ ^\mu- " , false ) ;
 1010
 1020// get B-candidate const LHCb::Particle* B = ... ;
 1030
 1040// use the functor const double value_L = cosTheta_L ( B ) ;
 1050

Python:

 1000## create the functors cosTheta_L = COSPOL ( 'B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) ^\mu+ \mu- ', 'B0 --&gt; ( K*(892)0 -&gt; K- \pi^+ ) \mu+ ^\mu- ' , False )
 1010
 1020## get B-candidate B = ...
 1030
 1040## use the functor value_L = cosTheta_L ( B )
 1050

The child particles coudl be specified also using decay nodes or particle functors:

 1000// create the functors using ``decay nodes'' from PartProp.Nodes module const COSPOL cosTheta_L = COSPOL ( EllPlus , EllMinus , False )
 1010
 1020// create the functors using ``decay nodes'' from PartProp.Nodes module const COSPOL cosTheta_K = COSPOL ( Hadron & Positive & Strange , Pid("K*(892)0") )
 1030
 1040// create the functors using particle cuts const COSPOL cosTheta_L = COSPOL ( "mu+" <span>= ID , "mu-" =</span> ID , False )
 1050
 1060// create the functors using particle cuts const COSPOL cosTheta_K = COSPOL ( "K+" <span>= ID , "K*(892)*" =</span> ID )
 1070

 1000## create the functors using ``decay nodes'' from PartProp.Nodes module cosTheta_L = COSPOL ( EllPlus , EllMinus , False )
 1010
 1020## create the functors using ``decay nodes'' from PartProp.Nodes module cosTheta_K = COSPOL ( Hadron & Positive & Strange , Pid('K*(892)0') )
 1030
 1040## create the functors using particle cuts cosTheta_L = COSPOL ( 'mu+' <span>= ID , 'mu-' =</span> ID , False )
 1050
 1060## create the functors using particle cuts cosTheta_K = COSPOL ( 'K+' <span>= ID , 'K*(892)*' =</span> ID )
 1070
The actual computations are perfomed in function LoKi::Kinematics::decayAngle using the explicit Lorentz-invariant expression

The angle between decay planes

For study of decays such as or it is important to evaluat the angle between the decay planes. The functors SINCHI, COSCHI and ANGLECHI allows to calculate , and angle iself respectively. One needs to specify four child particles for evaluation of the angles:

C++

 1000// create the functors const SINCHI sinChi = SINCHI ( "B0 --&gt; ( K*(892)0 -&gt; ^K- \pi+ ) \mu+ \mu- ", "B0 --&gt; ( K*(892)0 -&gt; K- ^\pi+ ) \mu+ \mu- " , "B0 --&gt; ( K*(892)0 -&gt; K- \pi+ ) ^\mu+ \mu- ", "B0 --&gt; ( K*(892)0 -&gt; K- \pi+ ) \mu+ ^\mu- " ) ;
 1010

Python:

 1000## create the functors sinChi = SINCHI ( "B0 --&gt; ( K*(892)0 -&gt; ^K- \pi+ ) \mu+ \mu- ", "B0 --&gt; ( K*(892)0 -&gt; K- ^\pi+ ) \mu+ \mu- " , "B0 --&gt; ( K*(892)0 -&gt; K- \pi+ ) ^\mu+ \mu- ", "B0 --&gt; ( K*(892)0 -&gt; K- \pi+ ) \mu+ ^\mu- " ) 
 1010

Again decay nodes and particle functors can be used to select proper children particles:

C++

 1000// create the functors const SINCHI sinChi = SINCHI ( EllPlus , ElMinus , Meson & Stranage & Positive , Meson & Strange & Negative ) ; const COSCHI cosChi = COSCHI ( "mu+" <span>= ID , "mu-" =</span> ID , "K+" <span>= ID , "K-" =</span> ID ) ;
 1010

Python:

 1000## create the functors sinChi = SINCHI ( EllPlus , ElMinus , Meson & Stranage & Positive , Meson & Strange & Negative ) cosChi = COSCHI ( 'mu+' <span>= ID , 'mu-' =</span> ID , 'K+' == ID , 'K-' = ID ) 
 1010

The actual computation are perfromed in functions

  • LoKi::Kinematics::sinDecayAngleChi,
  • LoKi::Kinematics::cosDecayAngleChi
  • LoKi::Kinematics::decayAngleChi
The explicit Lorentz-invariant expressions are used:
  • ,
where "4-normales" are defined as:
The 4-momenta of two compounds are:
  • ;
And the overall 4-momenta of decay head is .

The angles in transversity frame

For study of often transversity frame is used. For evaluation of angle (polarization angle of -meson) one can use the functor COSPOL( "B_s0 -> J/psi(1S) ( phi(1020) -> ^K+ K-) " , "B_s0 -> J/psi(1S) ^( phi(1020) -> K+ K-) " ) as described in previos chapter. For evaluation of one need to use the symbol COSTHETATR:

 1000// create the functor const COSTHETATR cosThetaTr = COSTHETATR ( "B_s0 --&gt; ( J/psi(1S) -&gt; ^mu+ mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ ^mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; ^K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; K+ ^K- ) " ) ;
 1010

The computation is performed using the explicit Lorentz-invarinat expression:

, where ``4-normal'' is defined as , and .

In a similar way for evaluation of , and one can use the symbols SINPHITR, COSPHITR and ANGLEPHITR

 1000// create the functor(s)
 1010
 1020const SINPHITR sinPhiTr = SINPHITR ( "B_s0 --&gt; ( J/psi(1S) -&gt; ^mu+ mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ ^mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; ^K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; K+ ^K- ) " ) ;
 1030
 1040const COSTHETATR cosPhiTr = COSPHITR ( "B_s0 --&gt; ( J/psi(1S) -&gt; ^mu+ mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ ^mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; ^K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; K+ ^K- ) " ) ;
 1050
 1060const ANGLEPHITR anglePhiTr = ANGLEPHITR ( "B_s0 --&gt; ( J/psi(1S) -&gt; ^mu+ mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ ^mu- ) ( phi(1020) -&gt; K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; ^K+ K- ) ", "B_s0 --&gt; ( J/psi(1S) -&gt; mu+ mu- ) ( phi(1020) -&gt; K+ ^K- ) " ) ;

The evaluation of is performed using the explicit Lorentz-invariant expression:

, where 4-normal is defined as , , , and ``in-plane'' 4-vector is defined as .

The evaluation of is performed using the explicit Lorentz-invariant expression as angle between the ``in-plane'' vector and vector in rest frame of , where and the ``4-normal'' is defiend as , , .

How to use LoKi algorithm-filters ?

LoKi-algorothms-filters allows to filter events on the basic of some event properties, e.g. properties of LHCb::ODIN, LHCb::L0DUReport, LHCb::HltDecReports and many others. The basic filters are:

  • LoKi::ODINFilter
  • LoKi::L0Filter
  • LoKi::HDRFilter
  • LoKi::VoidFilter
All filters are used in the same way:

 1000from Configurables import LoKi __XXXFilter as Filter
 1010
 1020fltr = Filter ( 'Myfilter' , Code = ' here a python strion with loki-functors comes ' )

All of them have the major proeprty Code, that shoudl be valid python expression that evaluates to the LoKi-functor woth following signatures:

  • const LHCb::ODIN* bool in case of LoKi::ODINFilter
  • const LHCb::L0DUReport* bool in case of LoKi::L0Filter
  • const LHCb::HltDecReports* bool in case of LoKi::HDRFilter
  • void bool in case of LoKi::VoidFilter
All of them have property Premambulo, where one can add addiiton python lines to be used durong the evaluation of Code, e.g.

 1000from Confiigurables import LoKi __XXXFilter as Filter
 1010
 1020fltr = Filter ( 'Myfilter' , .. Preambulo = [ "from LoKiCore.math import *" , "from LoKiNumbers.decorators import *" ] ... ) 

All but LoKi::VoidFilter, have property Location, where one can specify non-default location of the coprrespoonidg objects in TES, e.g. it cvan be useful for reading of stripping reports:

 1000from Configurables import LoKi __HDRFilter as StripFilter
 1010
 1020fltr = StripFilter ( 'StripFilter' , .. Location = "/Event/Strip/Phys/DecReports" ... )

How to select the certain HLT -line ?

 1000from Configurables import LoKi __HDRFilter as Filter
 1010
 1020fltr = Filter ( 'MicroBias' , .. Code = " HLT_PASS_RE( 'Hlt1MBMicro.*Decision' ) " ... )

How to select the certain stripping -line ?

 1000from Configurables import LoKi __HDRFilter as StripFilter
 1010
 1020fltr = StripFilter ( 'StrippedDstars' , .. Code = " HLT_PASS( 'StrippingDstarPromptWithD02HHNoPtDecision' ) " ,
 1030
 1040Location = "/Event/Strip/Phys/DecReports" ... )

How to select MC-events with no pileup?

Here one can use LoKi::VoidFilter and check number of proton-proton collisions from LHCb::GenCollisioons container:

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'No-pileup' , .. Code = " 1 == CONTAINS ( 'Gen/Collisions') " , ## get from TES the container "Gen/Collision" and check its size... ... )
 1030

How to select MC-events with interesting particles/decays?

Here one can use LoKi::VoidFilter :

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'No-pileup' , .. Code = " MCSOURCE('MC/Particles', ' J/psi(1S) =&gt; l+ l-' ) &gt;&gt; ( MCPT &gt; 500 * MeV ) &gt;&gt; ( MCY &gt; 2.5 ) &gt;&gt; ~MCEMPTY " , Preambulo = [ "from LoKiMC.decorators import *" ] )

In this example we select events where there is at least one , that decays into a lepton pair (with possible emission of soft radiative photons) with certain cuts on the transverse momentum and rapidity of particle.

We also can select the particles fomr B-decays:

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'No-pileup' , .. Code = " MCSOURCE('MC/Particles', ' Xb --&gt; ( J/psi(1S) =&gt; l+ l- ) .... ' ) &gt;&gt; ( MCPT &gt; 500 * MeV ) &gt;&gt; ( MCY &gt; 2.5 ) &gt;&gt; ~MCEMPTY " Preambulo = [ "from LoKiMC.decorators import *" ] )

How to select events with multiple reconstructed primary vertices?

Here one can use LoKi::VoidFilter and check number of primary vertices from LHCb::GenCollisioons container:

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'Multy_PV' , .. Code = " 1 &lt; CONTAINS ( 'Rec/Vertex/Primary') " , ## get from TES the container "Rec/Vertex/Primary" and check its size... ... )
 1030

How to select events with certain multiplicity of long tracks?

Here one can use LoKi::VoidFilter :

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'TrackVFilter , .. Code = " TrSOURCE( 'Rec/Track/Best' , TrLONG ) &gt;&gt; ( TrSIZE &gt; 100 ) " , Preambulo = [ "from LoKiTracks.decorators import *" ] ... )
 1030
 1040

How to select events with at least one backward track?

Here one can use LoKi::VoidFilter :

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'TrackVFilter , .. Code = " TrSOURCE( 'Rec/Track/Best' , TrBACKWARD ) &gt;&gt; ~TrEMPTY " , Preambulo = [ "from LoKiTracks.decorators import *" ] ... )
 1030
 1040

How to select events with at least two good high-pt muons?

Here one can use LoKi::VoidFilter :

 1000from Configurables import LoKi __VoidFilter as Filter
 1010
 1020fltr = Filter ( 'TrackVFilter , .. Code = " SOURCE( 'Phys/StdLooseMuons' , ( PT &gt; 1.5 GeV ) & ISMUON & ( PIDmu &gt; 0 ) ) &gt;&gt; ( 2 &lt;= SIZE ) " , Preambulo = [ "from LoKiPhys.decorators import *" ] ... )
 1030
 1040


Vanya BELYAEV - 20 June 2k+10
Topic attachments
I Attachment History Action Size Date Who Comment
PDFpdf 20090324_LHCb-UK-Functors.pdf r1 manage 5394.6 K 2009-05-05 - 16:05 VanyaBelyaev  
Unknown file formatpptx 20090324_LHCb-UK-Functors.pptx r1 manage 275.1 K 2009-05-05 - 16:06 VanyaBelyaev  
Texttxt MCtest.py.txt r1 manage 6.8 K 2009-12-10 - 15:52 VanyaBelyaev  
Texttxt MCtest2.py.txt r1 manage 2.3 K 2009-12-10 - 15:56 VanyaBelyaev  
JPEGjpg snap.jpg r1 manage 948.3 K 2008-05-17 - 23:23 VanyaBelyaev Snapshot from LoKi::DecayTruth algorithm
Edit | Attach | Watch | Print version | History: r29 < r28 < r27 < r26 < r25 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r29 - 2016-04-08 - VanyaBelyaev
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb/FAQ All webs login

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