Belle II Software  release-06-02-00
VertexVariables.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/variables/VertexVariables.h>
10 #include <analysis/utility/ReferenceFrame.h>
11 
12 #include <framework/database/DBObjPtr.h>
13 #include <framework/logging/Logger.h>
14 #include <framework/utilities/Conversion.h>
15 
16 #include <TMatrixFSym.h>
17 #include <TVector3.h>
18 
19 #include <mdst/dbobjects/BeamSpot.h>
20 #include <mdst/dataobjects/MCParticle.h>
21 #include <mdst/dataobjects/Track.h>
22 #include <mdst/dataobjects/TrackFitResult.h>
23 
24 
25 namespace Belle2 {
30  class Particle;
31 
32  namespace Variable {
33 
34  static const double realNaN = std::numeric_limits<double>::quiet_NaN();
35 
36  // Generated vertex information
37  double mcDecayVertexX(const Particle* part)
38  {
39  auto* mcparticle = part->getMCParticle();
40  if (!mcparticle) return realNaN;
41  return mcparticle->getDecayVertex().X();
42  }
43 
44  double mcDecayVertexY(const Particle* part)
45  {
46  auto* mcparticle = part->getMCParticle();
47  if (!mcparticle) return realNaN;
48  return mcparticle->getDecayVertex().Y();
49  }
50 
51  double mcDecayVertexZ(const Particle* part)
52  {
53  auto* mcparticle = part->getMCParticle();
54  if (!mcparticle) return realNaN;
55  return mcparticle->getDecayVertex().Z();
56  }
57 
58  double mcDecayVertexRho(const Particle* part)
59  {
60  auto* mcparticle = part->getMCParticle();
61  if (!mcparticle) return realNaN;
62  return mcparticle->getDecayVertex().Perp();
63  }
64 
65  TVector3 getMcDecayVertexFromIP(const MCParticle* mcparticle)
66  {
67  static DBObjPtr<BeamSpot> beamSpotDB;
68  const auto& frame = ReferenceFrame::GetCurrent();
69  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition());
70  }
71 
72  double mcDecayVertexFromIPX(const Particle* part)
73  {
74  auto* mcparticle = part->getMCParticle();
75  if (!mcparticle) return realNaN;
76  return getMcDecayVertexFromIP(mcparticle).X();
77  }
78 
79  double mcDecayVertexFromIPY(const Particle* part)
80  {
81  auto* mcparticle = part->getMCParticle();
82  if (!mcparticle) return realNaN;
83  return getMcDecayVertexFromIP(mcparticle).Y();
84  }
85 
86  double mcDecayVertexFromIPZ(const Particle* part)
87  {
88  auto* mcparticle = part->getMCParticle();
89  if (!mcparticle) return realNaN;
90  return getMcDecayVertexFromIP(mcparticle).Z();
91  }
92 
93  double mcDecayVertexFromIPRho(const Particle* part)
94  {
95  auto* mcparticle = part->getMCParticle();
96  if (!mcparticle) return realNaN;
97  return getMcDecayVertexFromIP(mcparticle).Perp();
98  }
99 
100  double mcDecayVertexFromIPDistance(const Particle* part)
101  {
102  auto* mcparticle = part->getMCParticle();
103  if (!mcparticle) return realNaN;
104  return getMcDecayVertexFromIP(mcparticle).Mag();
105  }
106 
107  double mcProductionVertexX(const Particle* part)
108  {
109  auto* mcparticle = part->getMCParticle();
110  if (!mcparticle) return realNaN;
111  return mcparticle->getProductionVertex().X();
112  }
113 
114  double mcProductionVertexY(const Particle* part)
115  {
116  auto* mcparticle = part->getMCParticle();
117  if (!mcparticle) return realNaN;
118  return mcparticle->getProductionVertex().Y();
119  }
120 
121  double mcProductionVertexZ(const Particle* part)
122  {
123  auto* mcparticle = part->getMCParticle();
124  if (!mcparticle) return realNaN;
125  return mcparticle->getProductionVertex().Z();
126  }
127 
128  TVector3 getMcProductionVertexFromIP(const MCParticle* mcparticle)
129  {
130  static DBObjPtr<BeamSpot> beamSpotDB;
131  const auto& frame = ReferenceFrame::GetCurrent();
132  return frame.getVertex(mcparticle->getProductionVertex() - beamSpotDB->getIPPosition());
133  }
134 
135  double mcProductionVertexFromIPX(const Particle* part)
136  {
137  auto* mcparticle = part->getMCParticle();
138  if (!mcparticle) return realNaN;
139  return getMcProductionVertexFromIP(mcparticle).X();
140  }
141 
142  double mcProductionVertexFromIPY(const Particle* part)
143  {
144  auto* mcparticle = part->getMCParticle();
145  if (!mcparticle) return realNaN;
146  return getMcProductionVertexFromIP(mcparticle).Y();
147  }
148 
149  double mcProductionVertexFromIPZ(const Particle* part)
150  {
151  auto* mcparticle = part->getMCParticle();
152  if (!mcparticle) return realNaN;
153  return getMcProductionVertexFromIP(mcparticle).Z();
154  }
155 
156  // vertex or POCA in respect to origin ------------------------------
157 
158  double particleX(const Particle* part)
159  {
160  const auto& frame = ReferenceFrame::GetCurrent();
161  return frame.getVertex(part).X();
162  }
163 
164  double particleY(const Particle* part)
165  {
166  const auto& frame = ReferenceFrame::GetCurrent();
167  return frame.getVertex(part).Y();
168  }
169 
170  double particleZ(const Particle* part)
171  {
172  const auto& frame = ReferenceFrame::GetCurrent();
173  return frame.getVertex(part).Z();
174  }
175 
176  inline double getParticleUncertaintyByIndex(const Particle* part, unsigned int index)
177  {
178  if (!part) {
179  B2FATAL("The particle provide does not exist.");
180  }
181  const auto& errMatrix = part->getVertexErrorMatrix();
182  return std::sqrt(errMatrix(index, index));
183  }
184 
185  double particleDXUncertainty(const Particle* part)
186  {
187  // uncertainty on x (with respect to the origin)
188  return getParticleUncertaintyByIndex(part, 0);
189  }
190 
191  double particleDYUncertainty(const Particle* part)
192  {
193  // uncertainty on y (with respect to the origin)
194  return getParticleUncertaintyByIndex(part, 1);
195  }
196 
197  double particleDZUncertainty(const Particle* part)
198  {
199  // uncertainty on z (with respect to the origin)
200  return getParticleUncertaintyByIndex(part, 2);
201  }
202 
203  //----------------------------------------------------------------------------------
204  // vertex or POCA in respect to measured IP
205 
206  TVector3 getVertexD(const Particle* part)
207  {
208  static DBObjPtr<BeamSpot> beamSpotDB;
209  const auto& frame = ReferenceFrame::GetCurrent();
210  auto trackFit = part->getTrackFitResult();
211  if (!trackFit)
212  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition());
213 
214  UncertainHelix helix = trackFit->getUncertainHelix();
215  helix.passiveMoveBy(beamSpotDB->getIPPosition());
216  return frame.getVertex(helix.getPerigee());
217  }
218 
219 
220  double particleDX(const Particle* part)
221  {
222  return getVertexD(part).X();
223  }
224 
225  double particleDY(const Particle* part)
226  {
227  return getVertexD(part).Y();
228  }
229 
230  double particleDZ(const Particle* part)
231  {
232  return getVertexD(part).Z();
233  }
234 
235  double particleDRho(const Particle* part)
236  {
237  return getVertexD(part).Perp();
238  }
239 
240  double particleDPhi(const Particle* part)
241  {
242  return getVertexD(part).Phi();
243  }
244 
245  double particleDCosTheta(const Particle* part)
246  {
247  return getVertexD(part).CosTheta();
248  }
249 
250  double particleDistance(const Particle* part)
251  {
252  return getVertexD(part).Mag();
253  }
254 
255  double particleDistanceSignificance(const Particle* part)
256  {
257  // significance is defined as s = r/sigma_r, therefore:
258  // s &= \frac{r}{\sqrt{ \sum_{ij} \frac{\partial r}{x_i} V_{ij} \frac{\partial r}{x_j}}}
259  // &= \frac{r^2}{\sqrt{\vec{x}V\vec{x}}}
260  // where:
261  // r &= \sqrt{\vec{x}*\vec{x}}
262  // and V_{ij} is the covariance matrix
263  static DBObjPtr<BeamSpot> beamSpotDB;
264  const auto& frame = ReferenceFrame::GetCurrent();
265  const TVector3& vertex = frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition());
266  const TMatrixFSym& vertexErr = frame.getVertexErrorMatrix(static_cast<TMatrixDSym>(part->getVertexErrorMatrix()) +
267  beamSpotDB->getCovVertex());
268  const double denominator = vertex * (vertexErr * vertex);
269  if (denominator <= 0) return realNaN;
270 
271  return vertex.Mag2() / std::sqrt(denominator);
272  }
273 
274  // Production vertex position
275 
276  double particleProductionX(const Particle* part)
277  {
278  if (!part->hasExtraInfo("prodVertX")) return realNaN;
279  return part->getExtraInfo("prodVertX");
280  }
281 
282  double particleProductionY(const Particle* part)
283  {
284  if (!part->hasExtraInfo("prodVertY")) return realNaN;
285  return part->getExtraInfo("prodVertY");
286  }
287 
288  double particleProductionZ(const Particle* part)
289  {
290  if (!part->hasExtraInfo("prodVertZ")) return realNaN;
291  return part->getExtraInfo("prodVertZ");
292  }
293 
294  // Production vertex covariance matrix
295  Manager::FunctionPtr particleProductionCovElement(const std::vector<std::string>& arguments)
296  {
297  if (arguments.size() != 2) {
298  B2FATAL("Number of arguments of prodVertexCov function is incorrect!");
299  }
300 
301  int ielement = -1;
302  int jelement = -1;
303  try {
304  ielement = Belle2::convertString<int>(arguments[0]);
305  jelement = Belle2::convertString<int>(arguments[1]);
306  } catch (std::invalid_argument&) {
307  B2ERROR("Arguments of prodVertexCov function must be integer!");
308  return nullptr;
309  }
310 
311  if (std::min(ielement, jelement) < 0 || std::max(ielement, jelement) > 2) {
312  B2ERROR("Range of indexes of prodVertexCov function is incorrect!");
313  return nullptr;
314  }
315 
316  const std::vector<char> names = {'x', 'y', 'z'};
317  const std::string prodVertS = Form("prodVertS%c%c", names[ielement] , names[jelement]);
318 
319  return [prodVertS](const Particle * part) -> double {
320  if (!part->hasExtraInfo(prodVertS)) return realNaN;
321  return part->getExtraInfo(prodVertS);
322  };
323  }
324 
325  double particleProductionXErr(const Particle* part)
326  {
327  if (!part->hasExtraInfo("prodVertSxx")) return realNaN;
328  return std::sqrt(part->getExtraInfo("prodVertSxx"));
329  }
330 
331  double particleProductionYErr(const Particle* part)
332  {
333  if (!part->hasExtraInfo("prodVertSyy")) return realNaN;
334  return std::sqrt(part->getExtraInfo("prodVertSyy"));
335  }
336 
337  double particleProductionZErr(const Particle* part)
338  {
339  if (!part->hasExtraInfo("prodVertSzz")) return realNaN;
340  return std::sqrt(part->getExtraInfo("prodVertSzz"));
341  }
342 
343  VARIABLE_GROUP("Vertex Information");
344  // Generated vertex information
345  REGISTER_VARIABLE("mcDecayVertexX", mcDecayVertexX,
346  "Returns the x position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
347  REGISTER_VARIABLE("mcDecayVertexY", mcDecayVertexY,
348  "Returns the y position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
349  REGISTER_VARIABLE("mcDecayVertexZ", mcDecayVertexZ,
350  "Returns the z position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
351  REGISTER_VARIABLE("mcDecayVertexRho", mcDecayVertexRho,
352  "Returns the transverse position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
353  REGISTER_VARIABLE("mcDecayVertexFromIPX", mcDecayVertexFromIPX,
354  "Returns the x position of the decay vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
355  REGISTER_VARIABLE("mcDecayVertexFromIPY", mcDecayVertexFromIPY,
356  "Returns the y position of the decay vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
357  REGISTER_VARIABLE("mcDecayVertexFromIPZ", mcDecayVertexFromIPZ,
358  "Returns the z position of the decay vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
359  REGISTER_VARIABLE("mcDecayVertexFromIPRho", mcDecayVertexFromIPRho,
360  "Returns the transverse position of the decay vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
361  REGISTER_VARIABLE("mcDecayVertexFromIPDistance", mcDecayVertexFromIPDistance,
362  "Returns the distance of the decay vertex of the matched generated particle from the IP. Returns nan if the particle has no matched generated particle.");
363  REGISTER_VARIABLE("mcProductionVertexX", mcProductionVertexX,
364  "Returns the x position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
365  REGISTER_VARIABLE("mcProductionVertexY", mcProductionVertexY,
366  "Returns the y position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
367  REGISTER_VARIABLE("mcProductionVertexZ", mcProductionVertexZ,
368  "Returns the z position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
369  REGISTER_VARIABLE("mcProductionVertexFromIPX", mcProductionVertexFromIPX,
370  "Returns the x position of the production vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
371  REGISTER_VARIABLE("mcProductionVertexFromIPY", mcProductionVertexFromIPY,
372  "Returns the y position of the production vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
373  REGISTER_VARIABLE("mcProductionVertexFromIPZ", mcProductionVertexFromIPZ,
374  "Returns the z position of the production vertex of the matched generated particle wrt the IP. Returns nan if the particle has no matched generated particle.");
375 
376  // Decay vertex position
377  REGISTER_VARIABLE("distance", particleDistance,
378  R"DOC(3D distance between the IP and the particle decay vertex, if available.
379 
380 In case the particle has been created from a track, the distance is defined between the POCA and IP.
381 If the particle is built from an ECL cluster, the decay vertex is set to the nominal IP.
382 If the particle is created from a KLM cluster, the distance is calculated between the IP and the cluster itself.)DOC");
383 
384  REGISTER_VARIABLE("significanceOfDistance", particleDistanceSignificance,
385  "significance of distance from vertex or POCA to interaction point(-1 in case of numerical problems)");
386  REGISTER_VARIABLE("dx", particleDX, "vertex or POCA in case of tracks x in respect to IP");
387  REGISTER_VARIABLE("dy", particleDY, "vertex or POCA in case of tracks y in respect to IP");
388  REGISTER_VARIABLE("dz", particleDZ, "vertex or POCA in case of tracks z in respect to IP");
389  REGISTER_VARIABLE("x", particleX,
390  "x coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
391  REGISTER_VARIABLE("y", particleY,
392  "y coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
393  REGISTER_VARIABLE("z", particleZ,
394  "z coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
395  REGISTER_VARIABLE("x_uncertainty", particleDXUncertainty, "uncertainty on x (measured with respect to the origin)");
396  REGISTER_VARIABLE("y_uncertainty", particleDYUncertainty, "uncertainty on y (measured with respect to the origin)");
397  REGISTER_VARIABLE("z_uncertainty", particleDZUncertainty, "uncertainty on z (measured with respect to the origin)");
398  REGISTER_VARIABLE("dr", particleDRho, "transverse distance in respect to IP for a vertex; track d0 relative to IP for a track.");
399  REGISTER_VARIABLE("dphi", particleDPhi, "vertex azimuthal angle of the vertex or POCA in degrees in respect to IP");
400  REGISTER_VARIABLE("dcosTheta", particleDCosTheta, "vertex or POCA polar angle in respect to IP");
401  // Production vertex position
402  REGISTER_VARIABLE("prodVertexX", particleProductionX,
403  "Returns the x position of particle production vertex. Returns NaN if particle has no production vertex.");
404  REGISTER_VARIABLE("prodVertexY", particleProductionY,
405  "Returns the y position of particle production vertex.");
406  REGISTER_VARIABLE("prodVertexZ", particleProductionZ,
407  "Returns the z position of particle production vertex.");
408  // Production vertex covariance matrix
409  REGISTER_VARIABLE("prodVertexCov(i,j)", particleProductionCovElement,
410  "Returns the ij covariance matrix component of particle production vertex, arguments i,j should be 0, 1 or 2. Returns NaN if particle has no production covariance matrix.");
411  REGISTER_VARIABLE("prodVertexXErr", particleProductionXErr,
412  "Returns the x position uncertainty of particle production vertex. Returns NaN if particle has no production vertex.");
413  REGISTER_VARIABLE("prodVertexYErr", particleProductionYErr,
414  "Returns the y position uncertainty of particle production vertex.");
415  REGISTER_VARIABLE("prodVertexZErr", particleProductionZErr,
416  "Returns the z position uncertainty of particle production vertex.");
417 
418  }
420 }
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< double(const Particle *)> FunctionPtr
NOTE: the python interface is documented manually in analysis/doc/Variables.rst (because we use ROOT ...
Definition: Manager.h:108
static const double realNaN
shortcut for NaN of double type
Abstract base class for different kinds of events.