Belle II Software  release-05-01-25
VertexVariables.cc
1 /**************************************************************************
2 * BASF2 (Belle Analysis Framework 2) *
3 * Copyright(C) 2018 - Belle II Collaboration *
4 * *
5 * Author: The Belle II Collaboration *
6 * Contributors: Luigi Li Gioi, Sviatoslav Bilokin *
7 * *
8 * This software is provided "as is" without any warranty. *
9 **************************************************************************/
10 
11 #include <analysis/variables/VertexVariables.h>
12 #include <analysis/variables/TrackVariables.h>
13 #include <analysis/utility/ReferenceFrame.h>
14 
15 #include <framework/database/DBObjPtr.h>
16 #include <framework/logging/Logger.h>
17 #include <framework/utilities/Conversion.h>
18 
19 #include <boost/algorithm/string.hpp>
20 #include <boost/format.hpp>
21 
22 #include <TMatrixFSym.h>
23 #include <TVector3.h>
24 
25 #include <mdst/dbobjects/BeamSpot.h>
26 #include <mdst/dataobjects/MCParticle.h>
27 #include <mdst/dataobjects/Track.h>
28 #include <mdst/dataobjects/TrackFitResult.h>
29 
30 namespace Belle2 {
35  class Particle;
36 
37  namespace Variable {
38 
39  // Generated vertex information
40  double mcDecayVertexX(const Particle* part)
41  {
42  auto* mcparticle = part->getRelatedTo<MCParticle>();
43  if (mcparticle) {
44  return mcparticle->getDecayVertex().X();
45  }
46  return std::numeric_limits<double>::quiet_NaN();
47  }
48 
49  double mcDecayVertexY(const Particle* part)
50  {
51  auto* mcparticle = part->getRelatedTo<MCParticle>();
52  if (mcparticle) {
53  return mcparticle->getDecayVertex().Y();
54  }
55  return std::numeric_limits<double>::quiet_NaN();
56  }
57 
58  double mcDecayVertexZ(const Particle* part)
59  {
60  auto* mcparticle = part->getRelatedTo<MCParticle>();
61  if (mcparticle) {
62  return mcparticle->getDecayVertex().Z();
63  }
64  return std::numeric_limits<double>::quiet_NaN();
65  }
66 
67  double mcDecayVertexRho(const Particle* part)
68  {
69  auto* mcparticle = part->getRelatedTo<MCParticle>();
70  if (mcparticle) {
71  return mcparticle->getDecayVertex().Perp();
72  }
73  return std::numeric_limits<double>::quiet_NaN();
74  }
75 
76  double mcDecayVertexFromIPX(const Particle* part)
77  {
78  auto* mcparticle = part->getRelatedTo<MCParticle>();
79  if (mcparticle) {
80  static DBObjPtr<BeamSpot> beamSpotDB;
81  const auto& frame = ReferenceFrame::GetCurrent();
82  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition()).X();
83  }
84  return std::numeric_limits<double>::quiet_NaN();
85  }
86 
87  double mcDecayVertexFromIPY(const Particle* part)
88  {
89  auto* mcparticle = part->getRelatedTo<MCParticle>();
90  if (mcparticle) {
91  static DBObjPtr<BeamSpot> beamSpotDB;
92  const auto& frame = ReferenceFrame::GetCurrent();
93  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition()).Y();
94  }
95  return std::numeric_limits<double>::quiet_NaN();
96  }
97 
98  double mcDecayVertexFromIPZ(const Particle* part)
99  {
100  auto* mcparticle = part->getRelatedTo<MCParticle>();
101  if (mcparticle) {
102  static DBObjPtr<BeamSpot> beamSpotDB;
103  const auto& frame = ReferenceFrame::GetCurrent();
104  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition()).Z();
105  }
106  return std::numeric_limits<double>::quiet_NaN();
107  }
108 
109  double mcDecayVertexFromIPRho(const Particle* part)
110  {
111  auto* mcparticle = part->getRelatedTo<MCParticle>();
112  if (mcparticle) {
113  static DBObjPtr<BeamSpot> beamSpotDB;
114  const auto& frame = ReferenceFrame::GetCurrent();
115  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition()).Perp();
116  }
117  return std::numeric_limits<double>::quiet_NaN();
118  }
119 
120  double mcDecayVertexFromIPDistance(const Particle* part)
121  {
122  auto* mcparticle = part->getRelatedTo<MCParticle>();
123  if (mcparticle) {
124  static DBObjPtr<BeamSpot> beamSpotDB;
125  const auto& frame = ReferenceFrame::GetCurrent();
126  return frame.getVertex(mcparticle->getDecayVertex() - beamSpotDB->getIPPosition()).Mag();
127  }
128  return std::numeric_limits<double>::quiet_NaN();
129  }
130 
131  double mcProductionVertexX(const Particle* part)
132  {
133  auto* mcparticle = part->getRelatedTo<MCParticle>();
134  if (mcparticle) {
135  return mcparticle->getProductionVertex().X();
136  }
137  return std::numeric_limits<double>::quiet_NaN();
138  }
139 
140  double mcProductionVertexY(const Particle* part)
141  {
142  auto* mcparticle = part->getRelatedTo<MCParticle>();
143  if (mcparticle) {
144  return mcparticle->getProductionVertex().Y();
145  }
146  return std::numeric_limits<double>::quiet_NaN();
147  }
148 
149  double mcProductionVertexZ(const Particle* part)
150  {
151  auto* mcparticle = part->getRelatedTo<MCParticle>();
152  if (mcparticle) {
153  return mcparticle->getProductionVertex().Z();
154  }
155  return std::numeric_limits<double>::quiet_NaN();
156  }
157 
158  double mcProductionVertexFromIPX(const Particle* part)
159  {
160  auto* mcparticle = part->getRelatedTo<MCParticle>();
161  if (mcparticle) {
162  static DBObjPtr<BeamSpot> beamSpotDB;
163  const auto& frame = ReferenceFrame::GetCurrent();
164  return frame.getVertex(mcparticle->getProductionVertex() - beamSpotDB->getIPPosition()).X();
165  }
166  return std::numeric_limits<double>::quiet_NaN();
167  }
168 
169  double mcProductionVertexFromIPY(const Particle* part)
170  {
171  auto* mcparticle = part->getRelatedTo<MCParticle>();
172  if (mcparticle) {
173  static DBObjPtr<BeamSpot> beamSpotDB;
174  const auto& frame = ReferenceFrame::GetCurrent();
175  return frame.getVertex(mcparticle->getProductionVertex() - beamSpotDB->getIPPosition()).Y();
176  }
177  return std::numeric_limits<double>::quiet_NaN();
178  }
179 
180  double mcProductionVertexFromIPZ(const Particle* part)
181  {
182  auto* mcparticle = part->getRelatedTo<MCParticle>();
183  if (mcparticle) {
184  static DBObjPtr<BeamSpot> beamSpotDB;
185  const auto& frame = ReferenceFrame::GetCurrent();
186  return frame.getVertex(mcparticle->getProductionVertex() - beamSpotDB->getIPPosition()).Z();
187  }
188  return std::numeric_limits<double>::quiet_NaN();
189  }
190 
191  // vertex or POCA in respect to origin ------------------------------
192 
193  double particleX(const Particle* part)
194  {
195  const auto& frame = ReferenceFrame::GetCurrent();
196  return frame.getVertex(part).X();
197  }
198 
199  double particleY(const Particle* part)
200  {
201  const auto& frame = ReferenceFrame::GetCurrent();
202  return frame.getVertex(part).Y();
203  }
204 
205  double particleZ(const Particle* part)
206  {
207  const auto& frame = ReferenceFrame::GetCurrent();
208  return frame.getVertex(part).Z();
209  }
210 
211  inline double getParticleUncertaintyByIndex(const Particle* part, unsigned int index)
212  {
213  if (!part) {
214  B2FATAL("The particle provide does not exist.");
215  }
216  const auto& errMatrix = part->getVertexErrorMatrix();
217  return std::sqrt(errMatrix(index, index));
218  }
219 
220  double particleDXUncertainty(const Particle* part)
221  {
222  // uncertainty on x (with respect to the origin)
223  return getParticleUncertaintyByIndex(part, 0);
224  }
225 
226  double particleDYUncertainty(const Particle* part)
227  {
228  // uncertainty on y (with respect to the origin)
229  return getParticleUncertaintyByIndex(part, 1);
230  }
231 
232  double particleDZUncertainty(const Particle* part)
233  {
234  // uncertainty on z (with respect to the origin)
235  return getParticleUncertaintyByIndex(part, 2);
236  }
237 
238  //----------------------------------------------------------------------------------
239  // vertex or POCA in respect to measured IP
240  double particleDX(const Particle* part)
241  {
242  static DBObjPtr<BeamSpot> beamSpotDB;
243  const auto& frame = ReferenceFrame::GetCurrent();
244  auto trackFit = getTrackFitResultFromParticle(part);
245  if (!trackFit) {
246  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).X();
247  } else {
248  UncertainHelix helix = trackFit->getUncertainHelix();
249  helix.passiveMoveBy(beamSpotDB->getIPPosition());
250  return frame.getVertex(helix.getPerigee()).X();
251  }
252  }
253 
254  double particleDY(const Particle* part)
255  {
256  static DBObjPtr<BeamSpot> beamSpotDB;
257  const auto& frame = ReferenceFrame::GetCurrent();
258  auto trackFit = getTrackFitResultFromParticle(part);
259  if (!trackFit) {
260  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).Y();
261  } else {
262  UncertainHelix helix = trackFit->getUncertainHelix();
263  helix.passiveMoveBy(beamSpotDB->getIPPosition());
264  return frame.getVertex(helix.getPerigee()).Y();
265  }
266  }
267 
268  double particleDZ(const Particle* part)
269  {
270  static DBObjPtr<BeamSpot> beamSpotDB;
271  const auto& frame = ReferenceFrame::GetCurrent();
272  auto trackFit = getTrackFitResultFromParticle(part);
273  if (!trackFit) {
274  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).Z();
275  } else {
276  UncertainHelix helix = trackFit->getUncertainHelix();
277  helix.passiveMoveBy(beamSpotDB->getIPPosition());
278  return frame.getVertex(helix.getPerigee()).Z();
279  }
280  }
281 
282  double particleDRho(const Particle* part)
283  {
284  static DBObjPtr<BeamSpot> beamSpotDB;
285  const auto& frame = ReferenceFrame::GetCurrent();
286  auto trackFit = getTrackFitResultFromParticle(part);
287  if (!trackFit) {
288  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).Perp();
289  } else {
290  UncertainHelix helix = trackFit->getUncertainHelix();
291  helix.passiveMoveBy(beamSpotDB->getIPPosition());
292  return frame.getVertex(helix.getPerigee()).Perp();
293  }
294  }
295 
296  double particleDPhi(const Particle* part)
297  {
298  static DBObjPtr<BeamSpot> beamSpotDB;
299  const auto& frame = ReferenceFrame::GetCurrent();
300  auto trackFit = getTrackFitResultFromParticle(part);
301  if (!trackFit) {
302  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).Phi();
303  } else {
304  UncertainHelix helix = trackFit->getUncertainHelix();
305  helix.passiveMoveBy(beamSpotDB->getIPPosition());
306  return frame.getVertex(helix.getPerigee()).Phi();
307  }
308  }
309 
310  double particleDCosTheta(const Particle* part)
311  {
312  static DBObjPtr<BeamSpot> beamSpotDB;
313  const auto& frame = ReferenceFrame::GetCurrent();
314  auto trackFit = getTrackFitResultFromParticle(part);
315  if (!trackFit) {
316  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).CosTheta();
317  } else {
318  UncertainHelix helix = trackFit->getUncertainHelix();
319  helix.passiveMoveBy(beamSpotDB->getIPPosition());
320  return frame.getVertex(helix.getPerigee()).CosTheta();
321  }
322  }
323 
324  double particleDistance(const Particle* part)
325  {
326  static DBObjPtr<BeamSpot> beamSpotDB;
327  const auto& frame = ReferenceFrame::GetCurrent();
328  auto trackFit = getTrackFitResultFromParticle(part);
329  if (!trackFit) {
330  return frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition()).Mag();
331  } else {
332  UncertainHelix helix = trackFit->getUncertainHelix();
333  helix.passiveMoveBy(beamSpotDB->getIPPosition());
334  return frame.getVertex(helix.getPerigee()).Mag();
335  }
336  }
337 
338  double particleDistanceSignificance(const Particle* part)
339  {
340  // significance is defined as s = r/sigma_r, therefore:
341  // s &= \frac{r}{\sqrt{ \sum_{ij} \frac{\partial r}{x_i} V_{ij} \frac{\partial r}{x_j}}}
342  // &= \frac{r^2}{\sqrt{\vec{x}V\vec{x}}}
343  // where:
344  // r &= \sqrt{\vec{x}*\vec{x}}
345  // and V_{ij} is the covariance matrix
346  static DBObjPtr<BeamSpot> beamSpotDB;
347  const auto& frame = ReferenceFrame::GetCurrent();
348  const auto& vertex = frame.getVertex(part->getVertex() - beamSpotDB->getIPPosition());
349  const auto& vertexErr = frame.getVertexErrorMatrix(static_cast<TMatrixDSym>(part->getVertexErrorMatrix()) +
350  beamSpotDB->getCovVertex());
351  auto denominator = vertex * (vertexErr * vertex);
352  if (denominator <= 0) {
353  return std::numeric_limits<double>::quiet_NaN();
354  }
355  return vertex.Mag2() / std::sqrt(denominator);
356  }
357 
358  // Production vertex position
359 
360  double particleProductionX(const Particle* part)
361  {
362  if (part->hasExtraInfo("prodVertX")) {
363  return part->getExtraInfo("prodVertX");
364  }
365  return std::numeric_limits<double>::quiet_NaN();
366  }
367 
368  double particleProductionY(const Particle* part)
369  {
370  if (part->hasExtraInfo("prodVertY")) {
371  return part->getExtraInfo("prodVertY");
372  }
373  return std::numeric_limits<double>::quiet_NaN();
374  }
375 
376  double particleProductionZ(const Particle* part)
377  {
378  if (part->hasExtraInfo("prodVertZ")) {
379  return part->getExtraInfo("prodVertZ");
380  }
381  return std::numeric_limits<double>::quiet_NaN();
382  }
383 
384  // Production vertex covariance matrix
385  Manager::FunctionPtr particleProductionCovElement(const std::vector<std::string>& arguments)
386  {
387  int ielement = -1;
388  int jelement = -1;
389  if (arguments.size() == 2) {
390  try {
391  ielement = Belle2::convertString<int>(arguments[0]);
392  jelement = Belle2::convertString<int>(arguments[1]);
393  } catch (std::invalid_argument&) {
394  B2ERROR("Arguments of prodVertexCov function must be integer!");
395  return nullptr;
396  }
397  }
398  if (ielement > -1 && jelement > -1 && ielement < 3 && jelement < 3) {
399  auto func = [ielement, jelement](const Particle * part) -> double {
400  std::vector<std::string> names = {"x", "y", "z"};
401  std::string prodVertS = boost::str(boost::format("prodVertS%s%s") % names[ielement] % names[jelement]);
402  if (part->hasExtraInfo(prodVertS))
403  {
404  return part->getExtraInfo(prodVertS);
405  }
406  return std::numeric_limits<double>::quiet_NaN();
407  };
408  return func;
409  }
410  B2WARNING("Arguments of prodVertexCov function are incorrect!");
411  return nullptr;
412  }
413 
414  double particleProductionXErr(const Particle* part)
415  {
416  if (part->hasExtraInfo("prodVertSxx")) {
417  return std::sqrt(part->getExtraInfo("prodVertSxx"));
418  }
419  return std::numeric_limits<double>::quiet_NaN();
420  }
421 
422  double particleProductionYErr(const Particle* part)
423  {
424  if (part->hasExtraInfo("prodVertSyy")) {
425  return std::sqrt(part->getExtraInfo("prodVertSyy"));
426  }
427  return std::numeric_limits<double>::quiet_NaN();
428  }
429 
430  double particleProductionZErr(const Particle* part)
431  {
432  if (part->hasExtraInfo("prodVertSzz")) {
433  return std::sqrt(part->getExtraInfo("prodVertSzz"));
434  }
435  return std::numeric_limits<double>::quiet_NaN();
436  }
437 
438  VARIABLE_GROUP("Vertex Information");
439  // Generated vertex information
440  REGISTER_VARIABLE("mcDecayVertexX", mcDecayVertexX,
441  "Returns the x position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
442  REGISTER_VARIABLE("mcDecayVertexY", mcDecayVertexY,
443  "Returns the y position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
444  REGISTER_VARIABLE("mcDecayVertexZ", mcDecayVertexZ,
445  "Returns the z position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
446  REGISTER_VARIABLE("mcDecayVertexRho", mcDecayVertexRho,
447  "Returns the transverse position of the decay vertex of the matched generated particle. Returns nan if the particle has no matched generated particle.");
448  REGISTER_VARIABLE("mcDecayVertexFromIPX", mcDecayVertexFromIPX,
449  "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.");
450  REGISTER_VARIABLE("mcDecayVertexFromIPY", mcDecayVertexFromIPY,
451  "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.");
452  REGISTER_VARIABLE("mcDecayVertexFromIPZ", mcDecayVertexFromIPZ,
453  "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.");
454  REGISTER_VARIABLE("mcDecayVertexFromIPRho", mcDecayVertexFromIPRho,
455  "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.");
456  REGISTER_VARIABLE("mcDecayVertexFromIPDistance", mcDecayVertexFromIPDistance,
457  "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.");
458  REGISTER_VARIABLE("mcProductionVertexX", mcProductionVertexX,
459  "Returns the x position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
460  REGISTER_VARIABLE("mcProductionVertexY", mcProductionVertexY,
461  "Returns the y position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
462  REGISTER_VARIABLE("mcProductionVertexZ", mcProductionVertexZ,
463  "Returns the z position of production vertex of matched generated particle. Returns nan if the particle has no matched generated particle.");
464  REGISTER_VARIABLE("mcProductionVertexFromIPX", mcProductionVertexFromIPX,
465  "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.");
466  REGISTER_VARIABLE("mcProductionVertexFromIPY", mcProductionVertexFromIPY,
467  "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.");
468  REGISTER_VARIABLE("mcProductionVertexFromIPZ", mcProductionVertexFromIPZ,
469  "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.");
470 
471  // Decay vertex position
472  REGISTER_VARIABLE("distance", particleDistance,
473  R"DOC(3D distance between the IP and the particle decay vertex, if available.
474 
475 In case the particle has been created from a track, the distance is defined between the POCA and IP.
476 If the particle is built from an ECL cluster, the decay vertex is set to the nominal IP.
477 If the particle is created from a KLM cluster, the distance is calculated between the IP and the cluster itself.)DOC");
478 
479  REGISTER_VARIABLE("significanceOfDistance", particleDistanceSignificance,
480  "significance of distance from vertex or POCA to interaction point(-1 in case of numerical problems)");
481  REGISTER_VARIABLE("dx", particleDX, "vertex or POCA in case of tracks x in respect to IP");
482  REGISTER_VARIABLE("dy", particleDY, "vertex or POCA in case of tracks y in respect to IP");
483  REGISTER_VARIABLE("dz", particleDZ, "vertex or POCA in case of tracks z in respect to IP");
484  REGISTER_VARIABLE("x", particleX,
485  "x coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
486  REGISTER_VARIABLE("y", particleY,
487  "y coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
488  REGISTER_VARIABLE("z", particleZ,
489  "z coordinate of vertex in case of composite particle, or point of closest approach (POCA) in case of a track");
490  REGISTER_VARIABLE("x_uncertainty", particleDXUncertainty, "uncertainty on x (measured with respect to the origin)");
491  REGISTER_VARIABLE("y_uncertainty", particleDYUncertainty, "uncertainty on y (measured with respect to the origin)");
492  REGISTER_VARIABLE("z_uncertainty", particleDZUncertainty, "uncertainty on z (measured with respect to the origin)");
493  REGISTER_VARIABLE("dr", particleDRho, "transverse distance in respect to IP for a vertex; track d0 relative to IP for a track.");
494  REGISTER_VARIABLE("dphi", particleDPhi, "vertex azimuthal angle of the vertex or POCA in degrees in respect to IP");
495  REGISTER_VARIABLE("dcosTheta", particleDCosTheta, "vertex or POCA polar angle in respect to IP");
496  // Production vertex position
497  REGISTER_VARIABLE("prodVertexX", particleProductionX,
498  "Returns the x position of particle production vertex. Returns NaN if particle has no production vertex.");
499  REGISTER_VARIABLE("prodVertexY", particleProductionY,
500  "Returns the y position of particle production vertex.");
501  REGISTER_VARIABLE("prodVertexZ", particleProductionZ,
502  "Returns the z position of particle production vertex.");
503  // Production vertex covariance matrix
504  REGISTER_VARIABLE("prodVertexCov(i,j)", particleProductionCovElement,
505  "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.");
506  REGISTER_VARIABLE("prodVertexXErr", particleProductionXErr,
507  "Returns the x position uncertainty of particle production vertex. Returns NaN if particle has no production vertex.");
508  REGISTER_VARIABLE("prodVertexYErr", particleProductionYErr,
509  "Returns the y position uncertainty of particle production vertex.");
510  REGISTER_VARIABLE("prodVertexZErr", particleProductionZErr,
511  "Returns the z position uncertainty of particle production vertex.");
512 
513  }
515 }
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::Variable::Manager::FunctionPtr
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:118
Belle2::ReferenceFrame::GetCurrent
static const ReferenceFrame & GetCurrent()
Get current rest frame.
Definition: ReferenceFrame.cc:28