Belle II Software  release-06-02-00
KLMClusterVariables.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 /* Own header. */
10 #include <analysis/variables/KLMClusterVariables.h>
11 
12 /* Analysis headers. */
13 #include <analysis/dataobjects/Particle.h>
14 #include <analysis/utility/PCmsLabTransform.h>
15 #include <analysis/VariableManager/Manager.h>
16 
17 /* Belle 2 headers. */
18 #include <framework/datastore/StoreArray.h>
19 #include <mdst/dataobjects/ECLCluster.h>
20 #include <mdst/dataobjects/KlId.h>
21 #include <mdst/dataobjects/KLMCluster.h>
22 #include <mdst/dataobjects/Track.h>
23 #include <mdst/dataobjects/TrackFitResult.h>
24 
25 using namespace std;
26 
27 namespace Belle2::Variable {
28 
29  double klmClusterKlId(const Particle* particle)
30  {
31  const KLMCluster* cluster = particle->getKLMCluster();
32  if (!cluster) {
33  return std::numeric_limits<double>::quiet_NaN();
34  }
35  const KlId* klid = cluster->getRelatedTo<KlId>();
36  if (!klid) {
37  return std::numeric_limits<double>::quiet_NaN();
38  }
39  return klid->getKlId();
40  }
41 
42  int klmClusterBelleTrackFlag(const Particle* particle)
43  {
44  const float angle = 0.24;
45  const KLMCluster* cluster = particle->getKLMCluster();
46  if (!cluster) {
47  return std::numeric_limits<int>::quiet_NaN();
48  }
49  const TVector3& pos = cluster->getClusterPosition();
50  StoreArray<TrackFitResult> tracks;
51  for (const TrackFitResult& track : tracks) {
52  const TVector3& trackPos = track.getPosition();
53  if (trackPos.Angle(pos) < angle) {
54  return 1;
55  }
56  }
57  return 0;
58  }
59 
60  int klmClusterBelleECLFlag(const Particle* particle)
61  {
62  const float angle = 0.24;
63  const KLMCluster* klmCluster = particle->getKLMCluster();
64  if (!klmCluster) {
65  return std::numeric_limits<int>::quiet_NaN();
66  }
67  const TVector3& klmClusterPos = klmCluster->getClusterPosition();
68  StoreArray<ECLCluster> eclClusters;
69  for (const ECLCluster& eclCluster : eclClusters) {
70  const TVector3& eclClusterPos = eclCluster.getClusterPosition();
71  if (eclClusterPos.Angle(klmClusterPos) < angle) {
72  return 1;
73  }
74  }
75  return 0;
76  }
77 
78  double klmClusterTiming(const Particle* particle)
79  {
80  const KLMCluster* cluster = particle->getKLMCluster();
81  if (!cluster) {
82  return std::numeric_limits<double>::quiet_NaN();
83  }
84  return cluster->getTime();
85  }
86 
87 
88  double klmClusterPositionX(const Particle* particle)
89  {
90  const KLMCluster* cluster = particle->getKLMCluster();
91  if (!cluster) {
92  return std::numeric_limits<double>::quiet_NaN();
93  }
94  return cluster->getClusterPosition().x();
95  }
96 
97 
98  double klmClusterPositionY(const Particle* particle)
99  {
100  const KLMCluster* cluster = particle->getKLMCluster();
101  if (!cluster) {
102  return std::numeric_limits<double>::quiet_NaN();
103  }
104  return cluster->getClusterPosition().y();
105  }
106 
107 
108  double klmClusterPositionZ(const Particle* particle)
109  {
110  const KLMCluster* cluster = particle->getKLMCluster();
111  if (!cluster) {
112  return std::numeric_limits<double>::quiet_NaN();
113  }
114  return cluster->getClusterPosition().z();
115  }
116 
117 
118  double klmClusterInnermostLayer(const Particle* particle)
119  {
120  const KLMCluster* cluster = particle->getKLMCluster();
121  if (!cluster) {
122  return std::numeric_limits<double>::quiet_NaN();
123  }
124  return cluster->getInnermostLayer();
125  }
126 
127 
128  double klmClusterLayers(const Particle* particle)
129  {
130  const KLMCluster* cluster = particle->getKLMCluster();
131  if (!cluster) {
132  return std::numeric_limits<double>::quiet_NaN();
133  }
134  return cluster->getLayers();
135  }
136 
137  double klmClusterEnergy(const Particle* particle)
138  {
139  const KLMCluster* cluster = particle->getKLMCluster();
140  if (!cluster) {
141  return std::numeric_limits<double>::quiet_NaN();
142  }
143  return cluster->getEnergy();
144  }
145 
146  double klmClusterMomentum(const Particle* particle)
147  {
148  const KLMCluster* cluster = particle->getKLMCluster();
149  if (!cluster) {
150  return std::numeric_limits<double>::quiet_NaN();
151  }
152  return cluster->getMomentumMag();
153  }
154 
155  double klmClusterIsBKLM(const Particle* particle)
156  {
157  const KLMCluster* cluster = particle->getKLMCluster();
158  if (!cluster) {
159  return std::numeric_limits<double>::quiet_NaN();
160  }
161  float clusterZ = cluster->getClusterPosition().Z();
162  if ((clusterZ > -180) && (clusterZ < 275)) {
163  return 1;
164  }
165  return 0;
166  }
167 
168  double klmClusterIsEKLM(const Particle* particle)
169  {
170  const KLMCluster* cluster = particle->getKLMCluster();
171  if (!cluster) {
172  return std::numeric_limits<double>::quiet_NaN();
173  }
174  float clusterZ = cluster->getClusterPosition().Z();
175  if ((clusterZ < -180) || (clusterZ > 275)) {
176  return 1;
177  }
178  return 0;
179  }
180 
181  double klmClusterIsForwardEKLM(const Particle* particle)
182  {
183  const KLMCluster* cluster = particle->getKLMCluster();
184  if (!cluster) {
185  return std::numeric_limits<double>::quiet_NaN();
186  }
187  float clusterZ = cluster->getClusterPosition().Z();
188  if (clusterZ > 275) {
189  return 1;
190  }
191  return 0;
192  }
193 
194  double klmClusterIsBackwardEKLM(const Particle* particle)
195  {
196  const KLMCluster* cluster = particle->getKLMCluster();
197  if (!cluster) {
198  return std::numeric_limits<double>::quiet_NaN();
199  }
200  float clusterZ = cluster->getClusterPosition().Z();
201  if (clusterZ < -180) {
202  return 1;
203  }
204  return 0;
205  }
206 
207  double klmClusterTheta(const Particle* particle)
208  {
209  const KLMCluster* cluster = particle->getKLMCluster();
210  if (!cluster) {
211  return std::numeric_limits<double>::quiet_NaN();
212  }
213  return cluster->getClusterPosition().Theta();
214  }
215 
216  double klmClusterPhi(const Particle* particle)
217  {
218  const KLMCluster* cluster = particle->getKLMCluster();
219  if (!cluster) {
220  return std::numeric_limits<double>::quiet_NaN();
221  }
222  return cluster->getClusterPosition().Phi();
223  }
224 
225  double maximumKLMAngleCMS(const Particle* particle)
226  {
227  // check there actually are KLM clusters in the event
228  StoreArray<KLMCluster> clusters;
229  if (clusters.getEntries() == 0) return std::numeric_limits<double>::quiet_NaN();
230 
231  // get the input particle's vector momentum in the CMS frame
232  PCmsLabTransform T;
233  const TVector3 pCms = (T.rotateLabToCms() * particle->get4Vector()).Vect();
234 
235  // find the KLM cluster with the largest angle
236  double maxAngle = 0.0;
237  for (int iKLM = 0; iKLM < clusters.getEntries(); iKLM++) {
238  const TVector3 clusterMomentumCms = (T.rotateLabToCms() * clusters[iKLM]->getMomentum()).Vect();
239  double angle = pCms.Angle(clusterMomentumCms);
240  if (angle > maxAngle) maxAngle = angle;
241  }
242  return maxAngle;
243  }
244 
245  double nKLMClusterTrackMatches(const Particle* particle)
246  {
247  const KLMCluster* cluster = particle->getKLMCluster();
248  if (!cluster)
249  return std::numeric_limits<double>::quiet_NaN();
250  size_t out = cluster->getRelationsFrom<Track>().size();
251  return double(out);
252  }
253 
254  double nMatchedKLMClusters(const Particle* particle)
255  {
256  Belle2::Particle::EParticleSourceObject particleSource = particle->getParticleSource();
257  if (particleSource == Particle::EParticleSourceObject::c_Track) {
258  return particle->getTrack()->getRelationsTo<KLMCluster>().size();
259  } else if (particleSource == Particle::EParticleSourceObject::c_ECLCluster) {
260  return particle->getECLCluster()->getRelationsTo<KLMCluster>().size();
261  } else {
262  return std::numeric_limits<double>::quiet_NaN();
263  }
264  }
265 
266  double nKLMClusterECLClusterMatches(const Particle* particle)
267  {
268  const KLMCluster* cluster = particle->getKLMCluster();
269  if (!cluster)
270  return std::numeric_limits<double>::quiet_NaN();
271  size_t out = cluster->getRelationsFrom<ECLCluster>().size();
272  return double(out);
273  }
274 
275  double klmClusterTrackDistance(const Particle* particle)
276  {
277  const KLMCluster* cluster = particle->getKLMCluster();
278  if (!cluster)
279  return std::numeric_limits<double>::quiet_NaN();
280  auto trackWithWeight = cluster->getRelatedFromWithWeight<Track>();
281  if (!trackWithWeight.first)
282  return std::numeric_limits<double>::quiet_NaN();
283  return 1. / trackWithWeight.second;
284  }
285 
286  VARIABLE_GROUP("KLM Cluster and KlongID");
287 
288  REGISTER_VARIABLE("klmClusterKlId", klmClusterKlId,
289  "Returns the KlId classifier output associated to the KLMCluster.");
290  REGISTER_VARIABLE("klmClusterBelleTrackFlag", klmClusterBelleTrackFlag,
291  "Returns the Belle-style Track flag.");
292  REGISTER_VARIABLE("klmClusterBelleECLFlag", klmClusterBelleECLFlag,
293  "Returns the Belle-style ECL flag.");
294  REGISTER_VARIABLE("klmClusterTiming", klmClusterTiming, R"DOC(
295 Returns the timing informationf of the associated KLMCluster.
296 
297 .. warning::
298  Currently the KLM has no time calibration. This leads to a huge discrepancy for the variable :b2:var:`klmClusterTiming` if one compares collisions and simulated data. Moreover, the distribution of the variable on collisions data has a very complicated structure, due to the different timing shifts of different KLM components.
299  It is recommended to not use it in any case until the KLM is calibrated, even for simulated data.
300 
301 )DOC");
302  REGISTER_VARIABLE("klmClusterPositionX", klmClusterPositionX, R"DOC(
303 Returns the :math:`x` position of the associated KLMCluster.
304 )DOC");
305  REGISTER_VARIABLE("klmClusterPositionY", klmClusterPositionY, R"DOC(
306 Returns the :math:`y` position of the associated KLMCluster.
307 )DOC");
308  REGISTER_VARIABLE("klmClusterPositionZ", klmClusterPositionZ, R"DOC(
309 Returns the :math:`z` position of the associated KLMCluster.
310 )DOC");
311  REGISTER_VARIABLE("klmClusterInnermostLayer", klmClusterInnermostLayer,
312  "Returns the number of the innermost KLM layer with a 2-dimensional hit of the associated KLMCluster.");
313  REGISTER_VARIABLE("klmClusterLayers", klmClusterLayers,
314  "Returns the number of KLM layers with 2-dimensional hits of the associated KLMCluster.");
315  REGISTER_VARIABLE("klmClusterEnergy", klmClusterEnergy, R"DOC(
316 Returns the energy of the associated KLMCluster.
317 
318 .. warning::
319  This variable returns an approximation of the energy: it uses :b2:var:`klmClusterMomentum` as momentum and the hypothesis that the KLMCluster is originated by a :math:`K_{L}^0`
320  (:math:`E_{\text{KLM}} = \sqrt{M_{K^0_L}^2 + p_{\text{KLM}}^2}`, where :math:`E_{\text{KLM}}` is this variable, :math:`M_{K^0_L}` is the :math:`K^0_L` mass and :math:`p_{\text{KLM}}` is :b2:var:`klmClusterMomentum`).
321  It should be used with caution, and may not be physically meaningful, especially for :math:`n` candidates.
322 
323 )DOC");
324  REGISTER_VARIABLE("klmClusterMomentum", klmClusterMomentum, R"DOC(
325 Returns the momentum magnitude of the associated KLMCluster.
326 
327 .. warning::
328  This variable returns an approximation of the momentum, since it is proportional to :b2:var:`klmClusterLayers`
329  (:math:`p_{\text{KLM}} = 0.215 \cdot N_{\text{layers}}`, where :math:`p_{\text{KLM}}` is this variable and :math:`N_{\text{layers}}` is :b2:var:`klmClusterLayers`).
330  It should be used with caution, and may not be physically meaningful.
331 
332 )DOC");
333  REGISTER_VARIABLE("klmClusterIsBKLM", klmClusterIsBKLM,
334  "Returns 1 if the associated KLMCluster is in barrel KLM.");
335  REGISTER_VARIABLE("klmClusterIsEKLM", klmClusterIsEKLM,
336  "Returns 1 if the associated KLMCluster is in endcap KLM.");
337  REGISTER_VARIABLE("klmClusterIsForwardEKLM", klmClusterIsForwardEKLM,
338  "Returns 1 if the associated KLMCluster is in forward endcap KLM.");
339  REGISTER_VARIABLE("klmClusterIsBackwardEKLM", klmClusterIsBackwardEKLM,
340  "Returns 1 if the associated KLMCluster is in backward endcap KLM.");
341  REGISTER_VARIABLE("klmClusterTheta", klmClusterTheta, R"DOC(
342 Returns the polar (:math:`\theta`) angle of the associated KLMCluster.
343 )DOC");
344  REGISTER_VARIABLE("klmClusterPhi", klmClusterPhi, R"DOC(
345 Returns the azimuthal (:math:`\phi`) angle of the associated KLMCluster.
346 )DOC");
347  REGISTER_VARIABLE("maximumKLMAngleCMS", maximumKLMAngleCMS ,
348  "Returns the maximum angle in the CMS frame between the Particle and all KLMClusters in the event.");
349  REGISTER_VARIABLE("nKLMClusterTrackMatches", nKLMClusterTrackMatches, R"DOC(
350 Returns the number of Tracks matched to the KLMCluster associated to this Particle. This variable can return a number greater than 0 for :math:`K_{L}^0` or :math:`n` candidates originating from KLMClusters and returns NaN for Particles with no KLMClusters associated.
351 )DOC");
352  REGISTER_VARIABLE("nMatchedKLMClusters", nMatchedKLMClusters, R"DOC(
353  Returns the number of KLMClusters matched to the particle. It only works for
354  Particles created either from Tracks or from ECLCluster, while it returns NaN
355  for :math:`K_{L}^0` or :math:`n` candidates originating from KLMClusters.
356  )DOC");
357  REGISTER_VARIABLE("nKLMClusterECLClusterMatches", nKLMClusterECLClusterMatches, R"DOC(
358  Returns the number of ECLClusters matched to the KLMCluster associated to this Particle.
359  )DOC");
360  REGISTER_VARIABLE("klmClusterTrackDistance", klmClusterTrackDistance, R"DOC(
361 Returns the distance between the Track and the KLMCluster associated to this Particle. This variable returns NaN if there is no Track-to-KLMCluster relationship.
362 
363 .. note::
364 
365  When used over samples (data or MC) produced with release-06 or newer releases, the variable returns values
366  in cm; otherwise, over samples produced with release-05 or older releases, the variable returns values in mm.
367  )DOC");
368 
369 }
EParticleSourceObject
particle source enumerators
Definition: Particle.h:81