This is all about the advanced configuration of
DecayTreeTuple
.
Slides
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.
LoKi::Hybrid::TupleTool
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):
MCTruth=tuple.addTupleTool("TupleToolMCTruth")
MCTruth.addTupleTool("MCTupleToolKinematic")
MCTruth.addTupleTool("MCTupleToolHierarchy")
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
Branches
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=tuple.B.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_B")
LoKi_B.Variables = {
"PID" : "ID"
, "BPVDIRA" : "BPVDIRA"
, "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=branch.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_K")
atool.Variables = {
"PID" : "ID"
, "P2" : "P*P"
, "TrChi2" : "TRCHI2DOF"
}
mySharedConf(tuple.KPlus)
mySharedConf(tuple.KMinus)
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
- Run it!
- Check the ntuple with root
root -l Tutorial7.root
Problems?
- 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 *
??
Excercise:
- Alter the LoKi::Hybrid::TupleTool to operate on the muons instead.
- Expand the sets of variables to add DLL PID information.
- Add a branch specifically for the J/Psi.
- Add a LoKi::Hybrid::TupleTool to that branch with:
- the mass difference from the PDG J/Psi value
- 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.
- Copy an existing TupleTool to get the structure. Use TupleToolTutorial from
solutions/DaVinci7/TupleToolTutorial.h++cpp
.
- Add into the Fill method
- The particle's Charge
- The Pseudorapidity
- 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() );
}
else
{
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
private:
bool m_abs;
//in Constructor
declareProperty("absCharge",m_abs=false);
//then check what it is in the fill method, to steer what is actually filled
Run
- Compile the code
- Add your custom TupleTool to the list
- Run it!
Next:
--
RobLambert - 07 Jun 2009
--
PatrickSKoppenburg - 16-Oct-2012
--
PatrickSKoppenburg - 30-Sep-2013