DaVinci Tutorial 7

This is all about the advanced configuration of DecayTreeTuple.


This tutorial corresponds to the slides "New developments in DecayTreeTuple" last shown at software week here.

To configure or not to configure?

If you are content with the default version of a specific TupleTool, then just add it to the ToolList as shown in DaVinciTutorial6. However, if you also want to change the options of that tool, you must get a handle on the configurable which is used to control the options.

Configurables etc. should be very familiar to you from doing the Gaudi tutorials. If not, please go and do them. How this relates to configuration of TupleTools is described in detail in the TupleToolsAndConfigurables advanced tutorial. In our case the adding of tools is greatly simplified by some simple wrappers.

To use a tool without configuring it, just add it: ntuple.ToolList+=['TupleToolSomething/instance']

Then if you realize you need to configure it, instead do: myTool=ntuple.addTupleTool('TupleToolSomething/instance')

This will give you the configurable of this tool so you can edit the options.


The LoKi::Hybrid::TupleTool is the most powerful of all the TupleTools. With it you can add anything which exists in the LoKi combine particles framework. The calculation made within LoKi for certain distance parameters is often subtly different to what is done by the dedicated TupleTools, by using LoKi::Hybrid::TupleTool for everything you will cut on, you remove the ambiguity.

A point which is usually made strongly in the tutorials is that if you are training a selection, you should use the LoKi::Hybrid::TupleTool for everything that exists there and you intend to cut on, only use the other TupleTools for items which are not available in LoKi, rather than the other way around.

From your previous DecayTreeTuple (Solution to DaVinciTutorial6), add a LoKi::Hybrid::TupleTool

from DecayTreeTuple.Configuration import *
tuple = DecayTreeTuple("TutorialTree")
tuple.Decay = "[B_s0 -> ^(J/psi(1S) -> ^mu+ ^mu-) ^(phi(1020) -> ^K+ ^K-)]CC"
tuple.Inputs = [  SeqBs2JpsiPhi.outputLocation()]
# tuple.addTupleTool( "TupleToolGeometry") // already default
# tuple.addTupleTool( "TupleToolKinematic")// already default
tuple.addTupleTool( "TupleToolPropertime")
tuple.addTupleTool( "TupleToolPrimaries")
# tuple.addTupleTool( "TupleToolEventInfo")// already default
tuple.addTupleTool( "TupleToolTrackInfo")
tuple.addTupleTool( "TupleToolTagging")

Not that for most decays it is required to foresee the charge conjugated case, like tuple.Decay = "[B+ -> (^J/psi(1S) => ^mu+ ^mu-) ^K+]CC". J/psi Phi is a CP-eigenstate and therefore the flavour of the Bs is undefined. See LHCb.FAQ.LoKiNewDecayFinders for details about decay descriptors (from DaVinci v33r7).

The LoKi::Hybrid::TupleTool is similar to the LoKi::Hybrid::PlotTool you encountered in DaVinciTutorial4. With it you can add all variables know by the CombineParticles framework to your Tuple.

LoKi_All.Variables =  {
      "P" : "P"                                                                                           
    , "PT" : "PT"

More possibilities can be found at LHCb/LoKiHybridFilters

Configuring the MCTruth tools

(versions above v2r3) TupleToolMCTruth also takes a ToolList, of information to fill about each associated particle, and can also be configured with addTupleTool

if (simulation):

TupleToolMCTruth is like a mini DecayTreeTuple which fills other things inside your main DecayTreeTuple, just like a Branch. Remember, if you want to configure a TupleTool, use addTupleTool.

The ToolList is a list of MCParticleTupleTools, to see more examples of such tools you should refer to the talk given at software week here


Sometimes you may wish to have different information about different particles, or use more than one configuration of the same tool for different particles. For this you need to split your tuple into branches. Again there is a wrapper function for that.

tuple.addBranches({  # remove all "^" except where needed.
    "B" :  "^([B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ K-)]CC)",
    "KPlus" :  "[B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> ^K+ K-)]CC",
    "KMinus" :  "[B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ ^K-)]CC "

#add another tool to it with a different name
LoKi_B.Variables =  {
       "PID" : "ID"
    , "MassDiff_Bs0" : "DMASS('B_s0')" 
    , "VSep" : "MINTREE(ABSID=='J/psi(1S)',VFASPF(VZ))-MINTREE(ABSID=='phi(1020)',VFASPF(VZ))"

#or maybe you want two branches to have tools configured the same way. The best way to do this is with your own function.

def mySharedConf(branch):
  atool.Variables =  {
       "PID" : "ID"
    ,  "P2" : "P*P"                                                                                           
    ,  "TrChi2" : "TRCHI2DOF"


It is always a good idea to use branches, because it avoids adding useless entries to your ntuple, and prevents tools which are specific to certain particle types being blindly applied to everything.


  • Run it!
  • Check the ntuple with root root -l Tutorial7.root


  • If this didn't work, it's likely you didn't put everything into your configuration correctly... did you remember to include from DecayTreeTuple.Configuration import * ??


  1. Alter the LoKi::Hybrid::TupleTool to operate on the muons instead.
  2. Expand the sets of variables to add DLL PID information.
  3. Add a branch specifically for the J/Psi.
  4. Add a LoKi::Hybrid::TupleTool to that branch with:
    1. the mass difference from the PDG J/Psi value
    2. Vertex Chi2 per degree of freedom.

Adding your own TupleTool

In the rare case that there is something you need which isn't available in LoKi, and that isn't clearly available in an already existing TupleTool, you will need to write your own. It may inherit from either the IEventTupleTool, IParticleTupleTool or IMCParticleTupleTool, depending on the circumstances. Here we will write our own IParticleTupleTool.

  1. Copy an existing TupleTool to get the structure. Use TupleToolTutorial from solutions/DaVinci7/TupleToolTutorial.h++cpp.
  2. Add into the Fill method
    1. The particle's Charge
    2. The Pseudorapidity
    3. Some other information from the particle, as you like

StatusCode TupleToolTutorial::fill( const LHCb::Particle* 
				   , const LHCb::Particle* P
				   , const std::string& head
				   , Tuples::Tuple& tuple ){

  //fill some information about the particle here!
  bool test = true;
  if( P ){
    //fill some information here!
    test &= tuple->column( head+"_Q", P->charge() );
    test &= tuple->column( head+"_eta", P->momentum().Rapidity() );

    return StatusCode::FAILURE;
  return StatusCode(test);

Adding configuration to your TupleTool

You can use declareProperty in the constructor, as with any gaudi algorithm or tool, to help with configuration.

  • Declare a property which decides if it is the Charge, or the absolute value of the charge, which is input to the tuple.

//in header
  bool m_abs;

//in Constructor

//then check what it is in the fill method, to steer what is actually filled


  • Compile the code
  • Add your custom TupleTool to the list
  • Run it!


-- RobLambert - 07 Jun 2009 -- PatrickSKoppenburg - 16-Oct-2012 -- PatrickSKoppenburg - 30-Sep-2013

Edit | Attach | Watch | Print version | History: r32 < r31 < r30 < r29 < r28 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r32 - 2013-10-22 - PatrickSKoppenburg
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2021 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