Particle -> MC truth matching

This page is intended for documentation related to association between LHCb::Particles and LHCb::MCParticles in DaVinci. It describes new interfaces and implementations which are to replace the DaVinciAssociators, starting from DaVinci release v23r0. These interfaces differ from previous ones in that they are not designed to populate TES locations with the result of their calculations, but rather to give them back to the user. They also accept input containers of MCParticles and so are not limited to using asumed and standard TES locations for these. It is intended that through implementations of one or more of these, experts will have the necessary information to tune Particle to MCParticle association, and users will be able to benefit from the results through a simple and intuitive interface. It is of course possible for the user of these interfaces to be an algorithm that takes the results and puts them on the TES for re-use by other clients.

Particle -> MC truth relations are added to DecayTreeTuples with e.g. TupleToolMCTruth or TupleToolMCBackgroundInfo. Or they can be visualised with BkgTreePlotter.


New interfaces

  • IParticle2MCAssociator: Return a single associated MCParticle for a given reconstructed Particle
  • IParticle2MCWeightedAssociator: Return normalised weighted ranges of MCAssociations for a given Particle. Inherits from IParticle2MCAssociator
  • IP2MCP: In new package Phys/Particle2MCTruth. Return a boolean stating if an MCParticle and a Particle are matched, that is, if an MCParticle has contributed to a recunstructed Particle. Return tree structures with un-weighted MCParticles for a given recostructed Particle. The trees respect a parent to daughter ordering, and represent the MCParticles that contributed to the reconstructed Particle. Inherits from IParticle2MCAssociator.

Existing implementations:


The following implementations inherit from Particle2MCWeightedAssociatorBase (Kernel/Particle2MCWeightedAssociatorBase.h), which efficiently implements most methods of the public interface in terms of one or two methods. Implementations that inherit from this class only need to implement either the first two or the third of the following private methods

virtual double associationWeight(const LHCb::Particle*,
                                 const LHCb::MCParticle* ) const;

virtual bool isAssociated(const LHCb::Particle*,
                          const LHCb::MCParticle*  ) const;

virtual Particle2MCParticle::ToVector relatedMCPsImpl(const LHCb::Particle*,
                                                      const LHCb::MCParticle::ConstVector&) const ;

Both interfaces implement the relatedMCPsImpl method internally, and the common base class takes care of propagating the information through the public methods in a consistent way. There is an important limitation to both of these implementations. They both require MCParticles to be in the TES, so the input vector of MCParticles must be a subset of the MCParticles available on the TES.


The following implementation inherits from P2MCPBase (P2MCP/P2MCPBase.h), a self-consistent implementation of IP2MCP (and therefore IParticle2MCAssociator). Derived classes only have to implement matching and sorting methods:
virtual bool isMatched(const LHCb::Particle* particle, const LHCb::MCParticle* mcParticle) const ;

virtual P2MCP::Types::FlatTrees sort (const LHCb::MCParticle::ConstVector &mcParticles) const;
  • MCMatchObjP2MCRelator: Performs the association in two steps. First, it decides if an LHCb::Particle and an LHCb::MCParticle are matched using LoKi::MCMatch. Then, it splits and sorts the resulting set of associated MCParticles into decay sets, such that each set contains only MCParticles that come from different hierarchy levels in the same decay. More details are given in the MCMatchObjP2MCRelator section below. IParticle2MCAssociator::relatedMCP implementations, that is, getting one "best" MCParticle out of the trees, are not optimised yet.

BackgroundCategory as a composite associator

BackgroundCategory returns an associated MCParticle for a given composite Particle so long as the following criterion is met:

  • Each reconstructed final state daughter of the composite Particle has an associated MCParticle, and all these associated MCParticles have the same final MCParticle mother.

If this condition is fulfilled, the final MCParticle mother is returned as the associated MCParticle of the composite Particle being associated. Note that the presence of an associated MCParticle does not mean that the composite candidate is signal! For example, if the decay B_s0->D_s+ pi- is incorrectly reconstructed as B_s0->D_s+ K-, because the pion was misidentified as a kaon, the reconstructed B_s0 will have an associated B_s0 MCParticle, despite not being signal. In order to discover whether the composite particle is signal or not, the user should consult the category returned by the BackgroundCategory tool.

More detailed documentation on BackgroundCategory can be found in this talk and this public note.

Examples of use


In the header file, define a pointer to one of the interfaces above
#include "Kernel/IParticle2MCAssociator.h"
IParticle2MCAssociator* m_assoc;
Then, in the implementation,
// here you can use any of the implementations, DaVinciSmartAssociator, MCMatchObj2MCRelator
// or P2MCPFromProtoP if only interested in stable particles, 
// since they all implement IParticle2MCAssociator
m_assoc = tool<IParticle2MCAssociator >("MCMatchObjP2MCRelator");
And get the best associated particle:
const LHCb::Particle part = ...;
const LHCb::MCParticle* assocMCP = m_assoc->relatedMCP(part, LHCb::MCParticleLocation::Default);
Or get a range of associated LHCb::MCParticles using the smart associator:
// header file
IParticle2MCWeightedAssociator* m_assoc;
// implementation
m_assoc = tool<IParticle2MCAssociator>(DaVinciSmartAssociator);
const LHCb::Particle part = ...;
Particle2MCParticle::ToVector assocMCPs = m_assoc->relatedMCPs(part, LHCb::MCParticleLocation::Default);
Particle2MCParticle::ToVector::const_iterator iAssoc = assocMCPs.begin()
for ( ; iAssoc != assocMCPs.end() ; ++ iAssoc ) {
  verbose() << "Associated MCParticle at " << iAssoc->to() 
     << " with weight " << iAssoc->weight() << endmsg;

Similarly, one can get the tree-structure of MCParticles using IP2MCP:

// header
#include "P2MCP/IP2MCP.h"
IP2MCP* m_assoc;

// implementation

m_assoc = tool<IP2MCP>(MCMatchObjP2MCRelator);
const LHCb::Particle* part = ...'
typedef P2MCP::Types::Trees _Trees;
_Trees trees = m_assoc->relatedMCPs(part, LHCb::MCParticleLocation::Default);

In the above example, P2MCP::Types::Trees is a vector of vectors of MCParticle pointers. It is easier to illustrate their structure with a python example, see below.


All the interfaces decscibed above, plus the classes Particle2MCParticle::ToRange (std::vector of MCAssociations) and P2MCP::Types::FlatTrees (std::vector of std::vectors of MCParticle pointers) are accessible in GaudiPython, so it is quite easy to write python counterparts to the C++ examples above. However, note that the following examples are inside some event loop but independent of algorithms or sequences. This is quite standard for GaudiPython for all types of tools, not just the ones described here.
appMgr = AppMgr(outputlevel=4)
toolSvc = appMgr.toolsvc()
# get an instance of MCMatchObjP2MCRelator and DaVinciSmartAssociator.
# Also possible to get the IParticle2MCAssociator interface only, if not interested in ranges or trees.
MCMatchTool = toolSvc.create('MCMatchObjP2MCRelator', interface='IP2MCP')
SmartAssoc = toolSvc.create('DaVinciSmartAssociator', interface = 'IParticle2MCWeightedAssociator')
# loop over particles
evtSvc = appMgr.evtSvc()
while ( ... ) :
   particles = evtSvc[particlePath]
   for p in particles :
      trees = MCMatchTool.relatedMCPs(p)
      for tree in trees :
         for mcp in tree :
             print "found MCParticle ", mcp
      bestMatchedMCP = MCMatchTool.relatedMCP(p)
      print "Best match is ", bestMatchedMCP
      mcAssociations = SmartAssoc.relatedMCPs(p)
      for mcAssoc in mcAssociations :

Populating the TES with associations

Unlike the approach taken in DaVinciAssociators, the tools described above do not populate the TES by design. In order to do so, the simplest approach is to instrument a GaudiAlgorithm with one of the tools above, create a LHCb::Particle to LHCb::MCarticle relations table, and place it on the TES. There is currently one such algorithm available,P2MCRelatorAlg, which uses an MCMatchObjP2MCRelator to create the associations. The user has control of the location of the container of input particles, and the output relations table gets places in a standard location (see the doxygen documentation for details).


The MCMatchObjP2MCRelator associator returns a structure of LHCb::MCParticles that contributed to the reconstructed LHCb::Particle. For each LHCb::Particle, the structure is constructed in two steps. The structure is a P2MCP::Types::Trees, which is just a vector of vectors of MCParticle pointers. The creation of these structures is performed re-using some elegant ideas and components from LoKi, and the original explanation of point 1. below can be found in chapter 15 of the LoKi user guide.
  1. First, all the input LHCb::MCParticles are tested to see whether they are "matched" to the LHCb::Particle. This is performed using a LoKi::MCMatchObj. The result of the matching between a Particle and MCParticle pair is either true or false. To make the decision, the MCMatchObjP2MCRelator queries all of the input relations tables to see if the decision has already been made. These tables are accessible to the user via the RelTableLocations property. The default value is ["Relations/" + LHCb::ProtoParticleLocation::Charged, "Relations/" + LHCb::ProtoParticleLocation::Upstream, "Relations/" + LHCb::ProtoParticleLocation::Neutrals], meaning that the matching between stable Particles and MCParticles is taken as input. Behind the scenes, these input tables get generated on-demand from the linkers created by the DaVinciAssociators. The user can replace or add to these relations tables. In the case of stable reconstructed Particles, the tool uses the tables to perform direct matching. If no match is found, it tries to match the daughters of the MCParticle and so on, recursively. If a positive match is made somewhere down the decay tree, a positive match is given to all the MCParticles in that decay line. In the case of composite reconstructed Particles, the tool requires the positive MC matching of all daughter reconstructed particles for the particle with at least one MC particle from the expanded list of all daughter MCParticles for a given MCParticle mother. Again it is a recursive procedure, and it is overwritten if a direct match is already present in one of the input relations tables (not the default case). In this way, an association structure can be established starting from long-lived or so-called "stable" particles, that is, LHCb::Particles that originate from a LHCb::ProtoParticle that comes from an LHCb::Track or calorimeter deposits. At no point is the PID of LHCb::Particles or LHCb::MCParticles used.
  2. Secondly, the list of matched MCParticles is split and sorted by decay. That means that sets of particles that come from different Monte Carlo decays, or from separated branches of the same decay, will be separated into sub-lists. And within each list, the MCParticles are sorted in a mother-to-daughter order.
All of this is probably illustrated best with an example. The following has been produced with the P2MCP::DecayLines obtained from reconstructed particles:
Found  1  trees for particle  mu+

Found  1  trees for particle  phi(1020)

In general there should only be one tree per particle. However, there are cases where more than one LHCb::MCParticle can contribute to a single LHCb::Particle. This results in more than one tree:

Found  2  trees for particle  K+
In the example above, a mu+ has contributed enough hits to the reconstructed K+ to be considered to contribute to it. It's decay tree is truncated because the data set is a MicroDST, so not all the LHCb::MCParticles in the event have been stored.

-- JuanPalacios - 06 Jun 2009

Edit | Attach | Watch | Print version | History: r18 < r17 < r16 < r15 < r14 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r18 - 2015-05-11 - PaulSeyfert
    • 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