Belle II Software  release-06-02-00
TrackIsoCalculatorModule.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/TrackIsoCalculator/TrackIsoCalculatorModule.h>
10 
11 #include <cmath>
12 #include <iomanip>
13 
14 
15 
16 using namespace Belle2;
17 
18 REG_MODULE(TrackIsoCalculator)
19 
21 {
22  // Set module properties
23  setDescription(R"DOC(Calculate track isolation variables on the input ParticleList.)DOC");
24 
25  // Parameter definitions
26  addParam("particleList",
27  m_pListName,
28  "The name of the input ParticleList. Must be a charged stable particle as defined in Const::chargedStableSet.");
29  addParam("detectorInnerSurface",
30  m_detInnerSurface,
31  "The name of the detector at whose innermost layer we extrapolate each helix's polar and azimuthal angle. Allowed values: {CDC, PID(=TOP/ARICH), ECL, KLM}.");
32  addParam("use2DRhoPhiDist",
33  m_use2DRhoPhiDist,
34  "If true, will calculate the pair-wise track distance as the cord length on the (rho, phi) projection.",
35  bool(false));
36 }
37 
39 {
40 }
41 
43 {
44 
45  m_event_metadata.isRequired();
46  m_pList.isRequired(m_pListName);
47 
48  B2INFO("TrackIsoCalculator module will calculate isolation variables for the ParticleList: " << m_pListName << ".");
49 
50  m_extraInfoName = (!m_use2DRhoPhiDist) ? ("dist3DToClosestTrkAt" + m_detInnerSurface + "Surface") : ("dist2DRhoPhiToClosestTrkAt" +
51  m_detInnerSurface + "Surface");
52 }
53 
55 {
56 
57  if (!isStdChargedList()) {
58  B2FATAL("PDG: " << m_pList->getPDGCode() << " of ParticleList: " << m_pList->getParticleListName() <<
59  " is not that of a valid particle in Const::chargedStableSet! Aborting...");
60  }
61 
62  const auto nParticles = m_pList->getListSize();
63 
64  B2DEBUG(11, "EVENT: " << m_event_metadata->getEvent() << "\n" << "nParticles: " << nParticles);
65 
66  // Store the pair-wise distances in a 2D array.
67  // Size is given by the length of the particle list.
68  std::vector<double> defaultDistances(nParticles, 1e9);
69  std::vector<std::vector<double>> pairwiseDistances(nParticles, defaultDistances);
70 
71  B2DEBUG(11, "Array of pair-wise distances between tracks in particle list. Initial values:");
72  this->printDistancesArr(pairwiseDistances, nParticles);
73 
74  for (unsigned int iPart(0); iPart < nParticles; ++iPart) {
75 
76  Particle* iParticle = m_pList->getParticle(iPart);
77 
78  for (unsigned int jPart(iPart + 1); jPart < nParticles; ++jPart) {
79 
80  Particle* jParticle = m_pList->getParticle(jPart);
81 
82  // Calculate the pair-wise distance.
83  double ijDist = (!m_use2DRhoPhiDist) ? this->get3DDistAtDetSurface(iParticle,
84  jParticle) : this->get2DRhoPhiDistAsChordLength(iParticle, jParticle);
85 
86  pairwiseDistances[iPart][jPart] = ijDist;
87  pairwiseDistances[jPart][iPart] = ijDist;
88 
89  }
90 
91  }
92 
93  B2DEBUG(11, "Array of pair-wise distances between tracks in particle list. Final values:");
94  this->printDistancesArr(pairwiseDistances, nParticles);
95 
96  // For each particle index, find the index of the particle w/ minimal distance in the corresponding row of the 2D array.
97  for (unsigned int iPart(0); iPart < nParticles; ++iPart) {
98 
99  auto minDist = std::min_element(std::begin(pairwiseDistances[iPart]), std::end(pairwiseDistances[iPart]));
100  auto jPart = std::distance(std::begin(pairwiseDistances[iPart]), minDist);
101 
102  Particle* iParticle = m_pList->getParticle(iPart);
103 
104  B2DEBUG(10, m_extraInfoName << " = " << *minDist << " [cm] - Particle[" << iPart << "]'s closest partner at innermost " <<
105  m_detInnerSurface << " surface is Particle[" << jPart << "]");
106 
107  if (!iParticle->hasExtraInfo(m_extraInfoName)) {
108  B2DEBUG(10, "\tStoring extraInfo for Particle[" << iPart << "]...");
109  iParticle->writeExtraInfo(m_extraInfoName, *minDist);
110  }
111  }
112 
113 }
114 
116 {
117 }
118 
120 {
121 
122  // Radius and z boundaries of the cylinder describing this detector's inner surface.
123  const auto rho = m_detSurfBoundaries[m_detInnerSurface].m_rho;
124  const auto zfwd = m_detSurfBoundaries[m_detInnerSurface].m_zfwd;
125  const auto zbwd = m_detSurfBoundaries[m_detInnerSurface].m_zbwd;
126 
127  std::string nameExtTheta = "helixExtTheta(" + std::to_string(rho) + "," + std::to_string(zfwd) + "," + std::to_string(zbwd) + ")";
128  const auto iExtTheta = Variable::Manager::Instance().getVariable(nameExtTheta)->function(iParticle);
129  const auto jExtTheta = Variable::Manager::Instance().getVariable(nameExtTheta)->function(jParticle);
130 
131  std::string nameExtPhi = "helixExtPhi(" + std::to_string(rho) + "," + std::to_string(zfwd) + "," + std::to_string(zbwd) + ")";
132  const auto iExtPhi = Variable::Manager::Instance().getVariable(nameExtPhi)->function(iParticle);
133  const auto jExtPhi = Variable::Manager::Instance().getVariable(nameExtPhi)->function(jParticle);
134 
135  // Ok, we know theta and phi.
136  // Let's extract (spherical) R by using the transformation:
137  //
138  // 1. rho = r * sin(theta)
139  // 2. phi = phi
140  // 3. z = r * cos(theta)
141  //
142  // The formula to be inverted depends on where each extrapolated track's theta is found:
143  // if in barrel, use 1. (rho is known), if in fwd/bwd endcap, use 3. (zfwd/zbwd is known).
144 
145  const auto th_fwd = m_detSurfBoundaries[m_detInnerSurface].m_th_fwd;
146  const auto th_fwd_brl = m_detSurfBoundaries[m_detInnerSurface].m_th_fwd_brl;
147  const auto th_bwd_brl = m_detSurfBoundaries[m_detInnerSurface].m_th_bwd_brl;
148 
149  const auto iExtR = (iExtTheta >= th_fwd_brl && iExtTheta < th_bwd_brl) ? rho / sin(iExtTheta) : ((iExtTheta >= th_fwd
150  && iExtTheta < th_fwd_brl) ? zfwd / cos(iExtTheta) : zbwd / cos(iExtTheta));
151  const auto jExtR = (jExtTheta >= th_fwd_brl && jExtTheta < th_bwd_brl) ? rho / sin(jExtTheta) : ((jExtTheta >= th_fwd
152  && jExtTheta < th_fwd_brl) ? zfwd / cos(jExtTheta) : zbwd / cos(jExtTheta));
153 
154  // Now convert r, theta, phi to cartesian coordinates.
155  // 1. x = r * sin(theta) * cos(phi)
156  // 2. y = r * sin(theta) * sin(phi)
157  // 3. z = r * cos(theta)
158 
159  const auto iExtX = iExtR * sin(iExtTheta) * cos(iExtPhi);
160  const auto iExtY = iExtR * sin(iExtTheta) * sin(iExtPhi);
161  const auto iExtZ = iExtR * cos(iExtTheta);
162 
163  const auto jExtX = jExtR * sin(jExtTheta) * cos(jExtPhi);
164  const auto jExtY = jExtR * sin(jExtTheta) * sin(jExtPhi);
165  const auto jExtZ = jExtR * cos(jExtTheta);
166 
167  // Get 3D distance via Pythagoras.
168  return sqrt((iExtX - jExtX) * (iExtX - jExtX) + (iExtY - jExtY) * (iExtY - jExtY) + (iExtZ - jExtZ) * (iExtZ - jExtZ));
169 }
170 
171 
173 {
174 
175  // Radius and z boundaries of the cylinder describing this detector's inner surface.
176  const auto rho = m_detSurfBoundaries[m_detInnerSurface].m_rho;
177  const auto zfwd = m_detSurfBoundaries[m_detInnerSurface].m_zfwd;
178  const auto zbwd = m_detSurfBoundaries[m_detInnerSurface].m_zbwd;
179 
180  std::string nameExtPhi = "helixExtPhi(" + std::to_string(rho) + "," + std::to_string(zfwd) + "," + std::to_string(zbwd) + ")";
181  const auto iExtPhi = Variable::Manager::Instance().getVariable(nameExtPhi)->function(iParticle);
182  const auto jExtPhi = Variable::Manager::Instance().getVariable(nameExtPhi)->function(jParticle);
183 
184  auto diffPhi = jExtPhi - iExtPhi;
185  if (std::abs(diffPhi) > M_PI) {
186  diffPhi = (diffPhi > M_PI) ? diffPhi - 2 * M_PI : 2 * M_PI + diffPhi;
187  }
188 
189  return 2 * rho * sin(std::abs(diffPhi) / 2.0);
190 }
191 
192 void TrackIsoCalculatorModule::printDistancesArr(const std::vector<std::vector<double>>& arr, int size)
193 {
194 
195  auto logConfig = this->getLogConfig();
196 
197  if (logConfig.getLogLevel() == LogConfig::c_Debug && logConfig.getDebugLevel() >= 11) {
198  std::cout << "" << std::endl;
199  for (int i(0); i < size; ++i) {
200  for (int j(0); j < size; ++j) {
201  std::cout << std::setw(7) << arr[i][j] << " ";
202  }
203  std::cout << "\n";
204  }
205  std::cout << "" << std::endl;
206  }
207 }
@ c_Debug
Debug: for code development.
Definition: LogConfig.h:26
Base class for Modules.
Definition: Module.h:72
LogConfig & getLogConfig()
Returns the log system configuration.
Definition: Module.h:225
Class to store reconstructed particles.
Definition: Particle.h:74
void writeExtraInfo(const std::string &name, const float value)
Sets the user defined extraInfo.
Definition: Particle.cc:1261
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
Definition: Particle.cc:1219
Calculate track isolation variables on the input ParticleList.
std::unordered_map< std::string, DetSurfCylBoundaries > m_detSurfBoundaries
Map that associates to each detector its innermost layer's boundaries.
StoreObjPtr< EventMetaData > m_event_metadata
The event information.
~TrackIsoCalculatorModule() override
Destructor, use this to clean up anything you created in the constructor.
bool m_use2DRhoPhiDist
If true, will calculate the pair-wise track distance as the cord length on the (rho,...
void initialize() override
Use this to initialize resources or memory your module needs.
double get2DRhoPhiDistAsChordLength(Particle *iParticle, Particle *jParticle)
Calculate the 2D distance between the points where the two input extraplolated track helices cross th...
void event() override
Called once for each event.
std::string m_detInnerSurface
The name of the detector at whose innermost layer we extrapolate each track's polar and azimuthal ang...
void terminate() override
Module terminate().
double get3DDistAtDetSurface(Particle *iParticle, Particle *jParticle)
Calculate the 3D distance between the points where the two input extraplolated track helices cross th...
std::string m_pListName
The name of the input ParticleList.
void printDistancesArr(const std::vector< std::vector< double >> &arr, int size)
Print 2D array of pair-wise distances.
std::string m_extraInfoName
The name of the distance variable to be added to each particle as extraInfo.
bool isStdChargedList()
Check whether input particle list is of a valid charged stable particle.
StoreObjPtr< ParticleList > m_pList
The input ParticleList object.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:31
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:25
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.
FunctionPtr function
Pointer to function.
Definition: Manager.h:134