Belle II Software development
NeutralHadronMatcherModule.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <analysis/modules/NeutralHadronMatcher/NeutralHadronMatcherModule.h>
10
11#include <analysis/dataobjects/ParticleList.h>
12#include <analysis/variables/MCTruthVariables.h>
13
14#include <framework/datastore/StoreArray.h>
15#include <framework/datastore/StoreObjPtr.h>
16#include <framework/gearbox/Const.h>
17#include <mdst/dataobjects/MCParticle.h>
18
19#include <TRandom.h>
20
21using namespace Belle2;
22
23//-----------------------------------------------------------------
24// Register the Module
25//-----------------------------------------------------------------
26REG_MODULE(NeutralHadronMatcher);
27
28NeutralHadronMatcherModule::NeutralHadronMatcherModule() : Module()
29{
30 setDescription("Perform geometrical match between MC neutral hadron (given by mcPDG) and ECL clusters from the particleLists");
31 setPropertyFlags(c_ParallelProcessingCertified);
32 addParam("particleLists", m_ParticleLists, "Input particle list");
33 addParam("efficiencyCorrection", m_effcorr, "data/mc efficiency ratio", 0.83);
34 addParam("distanceCut", m_distance, "Matching distance", 15.0);
35 addParam("mcPDGcode", m_mcPDG, "MC PDG code of the neutral hadron", Const::Klong.getPDGCode());
36 addParam("ignoreClustersWithPDGcodes", m_PDGignore, "Do not attempt to match clusters that are already matched with specific codes",
37 std::vector<int> {Const::photon.getPDGCode()});
38}
39
41{
42 if (m_mcPDG == Const::Klong.getPDGCode()) {
43 m_infoName = "mcdistanceKL";
44 m_matchedId = "mdstIndexTruthKL";
45 } else if (abs(m_mcPDG) == Const::neutron.getPDGCode()) {
46 m_infoName = "mcdistanceNeutron";
47 m_matchedId = "mdstIndexTruthNeutron";
48 } else {
49 B2FATAL("Unsupported mcPDG value: " << m_mcPDG);
50 }
51
52 for (auto& iList : m_ParticleLists)
54
55 if (! StoreArray<MCParticle>().isValid())
56 B2WARNING("No MCParticles array found. Do you call the NeutralHadronMatcher with real data?");
57
58}
59
61{
62
63 StoreArray<MCParticle> mcparticles;
64 if (!mcparticles.isValid())
65 return;
66 if (mcparticles.getEntries() < 1)
67 B2FATAL("Missing mcparticles list for MC");
68
69 // Initialize extra info
70 for (auto& iList : m_ParticleLists) {
71 StoreObjPtr<ParticleList> particleList(iList);
72
73 //check particle List has particles
74 const size_t nPart = particleList->getListSize();
75 for (size_t iPart = 0; iPart < nPart; iPart++) {
76 auto particle = particleList->getParticle(iPart);
77 particle->addExtraInfo(m_infoName, 1.e10);
78 particle->addExtraInfo(m_matchedId, -1);
79 }
80 }
81
82 // collect only primary mcparticles that match m_mcPDG
83 std::vector< std::pair<MCParticle*, bool> > primaryMCParticles;
84 for (int i = 0; i < mcparticles.getEntries(); i++) {
85 auto mcPart = mcparticles[i];
86 if (mcPart->isPrimaryParticle() && abs(mcPart->getPDG()) == m_mcPDG) {
87 bool AddInefficiency = (gRandom->Uniform() > m_effcorr);
88 primaryMCParticles.push_back(std::pair(mcPart, AddInefficiency));
89 }
90 }
91
92 const size_t nMCPart = primaryMCParticles.size();
93
94 // if no primary MCParticles matching m_mcPDG exists, nothing to do.
95 if (nMCPart == 0)
96 return;
97
98 for (auto& iList : m_ParticleLists) {
99 StoreObjPtr<ParticleList> particleList(iList);
100
101 // loop over particles first
102 const size_t nPart = particleList->getListSize();
103 for (size_t iPart = 0; iPart < nPart; iPart++) {
104
105 auto particle = particleList->getParticle(iPart);
106 auto bestMatch = Variable::particleClusterBestMCPDGCode(particle);
107
108 if ((bestMatch) && (std::find(m_PDGignore.begin(), m_PDGignore.end(), int(bestMatch)) != m_PDGignore.end())) {
109 continue;
110 }
111
112 const ECLCluster* eclcluster = particle->getECLCluster();
113 if (!eclcluster) continue;
114
115 // create a vector of distances from MCParticles
116 std::vector< std::pair <double, bool> > distances;
117 distances.resize(nMCPart);
118
119 // loop over mcparticles
120 for (size_t iMCPart = 0; iMCPart < nMCPart; iMCPart++) {
121
122 auto mcPart = primaryMCParticles[iMCPart].first;
123
124 auto vtx = mcPart->getProductionVertex();
125 auto momentum = mcPart->getMomentum();
126
127 // got potential KL candidate
128 double R = eclcluster->getR();
129 double phi = eclcluster->getPhi();
130 double theta = eclcluster->getTheta();
131 double zcl = R / tan(theta);
132 double xcl = R * cos(phi);
133 double ycl = R * sin(phi);
134
135 double rECL = R; //cm
136 double z = vtx.Z() + rECL / tan(momentum.Theta());
137 double x = vtx.X() + rECL * cos(momentum.Phi());
138 double y = vtx.Y() + rECL * sin(momentum.Phi());
139
140 double dist = sqrt((x - xcl) * (x - xcl) + (y - ycl) * (y - ycl) + (z - zcl) * (z - zcl));
141 distances[iMCPart] = std::pair(dist, primaryMCParticles[iMCPart].second);
142 }
143
144 auto it_distMin = std::min_element(distances.begin(), distances.end(),
145 [](const auto & a, const auto & b) { return a.first < b.first;});
146 double distMin = (*it_distMin).first;
147 bool AddInefficiency = (*it_distMin).second;
148 if ((distMin < m_distance) && AddInefficiency)
149 distMin = -distMin;
150
151 particle->setExtraInfo(m_infoName, distMin);
152
153 if ((distMin < m_distance) && (distMin > 0))
154 particle->setExtraInfo(m_matchedId, primaryMCParticles[std::distance(distances.begin(), it_distMin)].first->getArrayIndex());
155
156 }
157 }
158
159}
160
161
double R
typedef autogenerated by FFTW
int getPDGCode() const
PDG code.
Definition: Const.h:473
static const ParticleType neutron
neutron particle
Definition: Const.h:675
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:678
static const ParticleType photon
photon particle
Definition: Const.h:673
ECL cluster data.
Definition: ECLCluster.h:27
double getPhi() const
Return Corrected Phi of Shower (radian).
Definition: ECLCluster.h:304
double getR() const
Return R.
Definition: ECLCluster.h:310
double getTheta() const
Return Corrected Theta of Shower (radian).
Definition: ECLCluster.h:307
Base class for Modules.
Definition: Module.h:72
std::vector< std::string > m_ParticleLists
input particle lists name
virtual void initialize() override final
Overridden initialize method.
double m_effcorr
input efficiency correction
std::string m_infoName
extra info variable for distance
virtual void event() override final
Overridden event method.
std::string m_matchedId
extra info variable for matched MC
std::vector< int > m_PDGignore
ignore clusters that are matched with the following PDG codes
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
bool isValid() const
Check whether the array was registered.
Definition: StoreArray.h:288
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:649
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.