Belle II Software  release-06-02-00
EventShapeCalculatorModule.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/utility/PCmsLabTransform.h>
10 
11 #include <analysis/modules/EventShapeCalculator/EventShapeCalculatorModule.h>
12 
13 #include <analysis/dataobjects/ParticleList.h>
14 #include <analysis/dataobjects/Particle.h>
15 
16 #include <framework/logging/Logger.h>
17 
18 #include <iostream>
19 
20 #include <analysis/ContinuumSuppression/Thrust.h>
21 #include <analysis/ContinuumSuppression/HarmonicMoments.h>
22 #include <analysis/ContinuumSuppression/CleoCones.h>
23 #include <analysis/ContinuumSuppression/FoxWolfram.h>
24 #include <analysis/ContinuumSuppression/SphericityEigenvalues.h>
25 
26 #include <TVector3.h>
27 #include <TLorentzVector.h>
28 
29 
30 using namespace std;
31 using namespace Belle2;
32 
33 //-----------------------------------------------------------------
34 // Register the Module
35 //-----------------------------------------------------------------
36 REG_MODULE(EventShapeCalculator)
37 
38 //-----------------------------------------------------------------
39 // Implementation
40 //-----------------------------------------------------------------
41 
43 {
44  // Set module properties
45  setDescription("Module to compute event shape attributes starting from particlelists. The core algorithms are not implemented in this module, but in dedicated basf2 classes.");
46  setPropertyFlags(c_ParallelProcessingCertified);
47  // Parameter definitions
48  addParam("particleListNames", m_particleListNames, "List of the ParticleLists to be used for the calculation of the EventShapes.",
49  vector<string>());
50  addParam("enableThrust", m_enableThrust, "Enables the calculation of thust-related quantities.", true);
51  addParam("enableCollisionAxis", m_enableCollisionAxis, "Enables the calculation of the quantities related to the collision axis.",
52  true);
53  addParam("enableFoxWolfram", m_enableFW, "Enables the calculation of the Fox-Wolfram moments.", true);
54  addParam("enableHarmonicMoments", m_enableHarmonicMoments, "Enables the calculation of the Harmonic moments.", true);
55  addParam("enableJets", m_enableJets, "Enables the calculation of jet-related quantities.", true);
56  addParam("enableSphericity", m_enableSphericity, "Enables the calculation of the sphericity-related quantities.", true);
57  addParam("enableCleoCones", m_enableCleoCones, "Enables the calculation of the CLEO cones.", true);
58  addParam("enableAllMoments", m_enableAllMoments, "Enables the calculation of FW and harmonic moments from 5 to 8", false);
59  addParam("checkForDuplicates", m_checkForDuplicates,
60  "Enables the check for duplicates in the input list. If a duplicate entry is found, the first one is kept.", false);
61 }
62 
63 
64 void EventShapeCalculatorModule::initialize()
65 {
66  m_eventShapeContainer.registerInDataStore();
67 }
68 
69 
70 void EventShapeCalculatorModule::event()
71 {
72 
74  double sqrtS = T.getCMSEnergy();
75 
76  if (!m_eventShapeContainer) m_eventShapeContainer.create();
77 
78  parseParticleLists(m_particleListNames);
79 
80 
81  // --------------------
82  // Calculates the FW moments
83  // --------------------
84  if (m_enableFW) {
85  FoxWolfram fw(m_p3List);
86  if (m_enableAllMoments) {
88  for (short i = 0; i < 9; i++) {
89  m_eventShapeContainer->setFWMoment(i, fw.getH(i));
90  }
91  } else {
93  for (short i = 0; i < 5; i++) {
94  m_eventShapeContainer->setFWMoment(i, fw.getH(i));
95  }
96  }
97  }
98 
99  // --------------------
100  // Calculates the sphericity quantities
101  // --------------------
102  if (m_enableSphericity) {
103  SphericityEigenvalues Sph(m_p3List);
104  Sph.calculateEigenvalues();
105  if (Sph.getEigenvalue(0) < Sph.getEigenvalue(1) || Sph.getEigenvalue(0) < Sph.getEigenvalue(2)
106  || Sph.getEigenvalue(1) < Sph.getEigenvalue(2))
107  B2WARNING("Eigenvalues not ordered!!!!!!!!!!");
108 
109  for (short i = 0; i < 3; i++) {
110  m_eventShapeContainer->setSphericityEigenvalue(i, Sph.getEigenvalue(i));
111  m_eventShapeContainer->setSphericityEigenvector(i, Sph.getEigenvector(i));
112  }
113  }
114 
115 
116  // --------------------
117  // Calculates thrust and thrust-related quantities
118  // --------------------
119  if (m_enableThrust) {
120  TVector3 thrust = Thrust::calculateThrust(m_p3List);
121  float thrustVal = thrust.Mag();
122  thrust = (1. / thrustVal) * thrust;
123  m_eventShapeContainer->setThrustAxis(thrust);
124  m_eventShapeContainer->setThrust(thrustVal);
125 
126  // --- If required, calculates the HarmonicMoments ---
127  if (m_enableHarmonicMoments) {
128  HarmonicMoments MM(m_p3List, thrust);
129  if (m_enableAllMoments) {
130  MM.calculateAllMoments();
131  for (short i = 0; i < 9; i++) {
132  auto moment = MM.getMoment(i, sqrtS);
133  m_eventShapeContainer->setHarmonicMomentThrust(i, moment);
134  }
135  } else {
136  MM.calculateBasicMoments();
137  for (short i = 0; i < 5; i++) {
138  auto moment = MM.getMoment(i, sqrtS);
139  m_eventShapeContainer->setHarmonicMomentThrust(i, moment);
140  }
141  }
142  }
143 
144  // --- If required, calculates the cleo cones w/ respect to the thrust axis ---
145  if (m_enableCleoCones) {
146  // Cleo cone class constructor. Unfortunately this class is designed
147  // to use the ROE, so the constructor takes two std::vector of momenta ("all" and "ROE"),
148  // then a vector to be used as axis, and finally two flags that determine if the cleo cones
149  // are calculated using the ROE, all the particles or both. Here we use the m_p3List as dummy
150  // list of the ROE momenta, that is however not used at all since the calculate only the
151  // cones with all the particles. This whole class would need some heavy restructuring...
152  CleoCones cleoCones(m_p3List, m_p3List, thrust, true, false);
153  std::vector<float> cones;
154  cones = cleoCones.cleo_cone_with_all();
155  for (short i = 0; i < 10; i++) {
156  m_eventShapeContainer->setCleoConeThrust(i, cones[i]);
157  }
158  } // end of if m_enableCleoCones
159 
160 
161  // --- If required, calculates the jet 4-momentum using the thrust axis ---
162  if (m_enableJets) {
163  TLorentzVector p4FWD(0., 0., 0., 0.);
164  TLorentzVector p4BKW(0., 0., 0., 0.);
165  for (const auto& p4 : m_p4List) {
166  if (p4.Vect().Dot(thrust) > 0)
167  p4FWD += p4;
168  else
169  p4BKW += p4;
170  }
171  m_eventShapeContainer->setForwardHemisphere4Momentum(p4FWD);
172  m_eventShapeContainer->setBackwardHemisphere4Momentum(p4BKW);
173  } // end of if m_enableJets
174  }// end of if m_enableThrust
175 
176 
177 
178  // --------------------
179  // Calculates the collision axis quantities
180  // --------------------
181  if (m_enableCollisionAxis) {
182 
183  TVector3 collisionAxis(0., 0., 1.);
184 
185  // --- If required, calculates the cleo cones w/ respect to the collision axis ---
186  if (m_enableCleoCones) {
187  CleoCones cleoCones(m_p3List, m_p3List, collisionAxis, true, false);
188  std::vector<float> cones;
189  cones = cleoCones.cleo_cone_with_all();
190  for (short i = 0; i < 10; i++) {
191  m_eventShapeContainer->setCleoConeCollision(i, cones[i]);
192  }
193  }
194 
195  // --- If required, calculates the HarmonicMoments ---
196  if (m_enableHarmonicMoments) {
197  HarmonicMoments MM(m_p3List, collisionAxis);
198  if (m_enableAllMoments) {
199  MM.calculateAllMoments();
200  for (short i = 0; i < 9; i++) {
201  auto moment = MM.getMoment(i, sqrtS);
202  m_eventShapeContainer->setHarmonicMomentCollision(i, moment);
203  }
204  } else {
205  MM.calculateBasicMoments();
206  for (short i = 0; i < 5; i++) {
207  auto moment = MM.getMoment(i, sqrtS);
208  m_eventShapeContainer->setHarmonicMomentCollision(i, moment);
209  }
210  }
211  } // end of m_enableHarmonicMoments
212  } // end of m_enableCollisionAxis
213 } // end of event()
214 
215 
216 
217 int EventShapeCalculatorModule::parseParticleLists(vector<string> particleListNames)
218 {
219  int nPart = 0; // number of particles
220 
222  m_p4List.clear();
223  m_p3List.clear();
224 
225  unsigned short nParticleLists = particleListNames.size();
226  if (nParticleLists == 0)
227  B2ERROR("No particle lists found. EventShape calculation not performed.");
228 
229  // This vector temporary stores the particle objects
230  // that have been processed so far (not only the momenta)
231  // in order to check for duplicates before pushing the 3- and 4- vectors
232  // in the corresponding lists
233  std::vector<Particle> tmpParticles;
234 
235  // Loops over the number of particle lists
236  for (unsigned short iList = 0; iList < nParticleLists; iList++) {
237  string particleListName = particleListNames[iList];
238  StoreObjPtr<ParticleList> particleList(particleListName);
239 
240  // Loops over the number of particles in the list
241  for (unsigned int iPart = 0; iPart < particleList->getListSize(); iPart++) {
242  const Particle* part = particleList->getParticle(iPart);
243 
244  // Flag to check for duplicates across the lists.
245  // It can be true only if m_checkForDuplicates is enabled
246  bool isDuplicate = false;
247 
248  if (m_checkForDuplicates) {
249  // loops over all the particles loaded so far
250  for (const auto& testPart : tmpParticles) {
251  if (testPart.isCopyOf(part)) {
252  B2WARNING("Duplicate particle found. The new one won't be used for the calculation of the event shape variables. Please, double check your input lists and try to make them mutually exclusive.");
253  isDuplicate = true;
254  break;
255  }
256  }
257  tmpParticles.push_back(*part);
258  }
259 
260  if (!isDuplicate) {
261  TLorentzVector p4CMS = T.rotateLabToCms() * part->get4Vector();
262  // it need to fill an std::vector of TVector3 to use the current FW routines.
263  // It will hopefully change in release 3
264  m_p4List.push_back(p4CMS);
265  m_p3List.push_back(p4CMS.Vect());
266  }
267  }
268  }
269  return nPart;
270 }
271 
Class to calculate the Cleo clone variables.
Definition: CleoCones.h:22
Module to compute event shape variables starting from three lists of particle objects (tracks,...
Class to calculate the Fox-Wolfram moments up to order 8.
Definition: FoxWolfram.h:28
void calculateAllMoments()
Method to perform the calculation of the moments up to order 8.
Definition: FoxWolfram.cc:57
void calculateBasicMoments()
Method to perform the calculation of the moments up to order 4, which are the most relevant ones.
Definition: FoxWolfram.cc:13
double getH(int i) const
Returns the i-th moment.
Definition: FoxWolfram.h:83
Class to calculate the Harmonic moments up to order 8 with respect to a given axis.
Base class for Modules.
Definition: Module.h:72
Class to hold Lorentz transformations from/to CMS and boost vector.
double getCMSEnergy() const
Returns CMS energy of e+e- (aka.
const TLorentzRotation rotateLabToCms() const
Returns Lorentz transformation from Lab to CMS.
Class to store reconstructed particles.
Definition: Particle.h:74
Class to calculate the Sphericity tensor eigenvalues and eigenvectors starting from an array of 3-mom...
TVector3 getEigenvector(short i) const
Returns the i-th Eigenvector.
void calculateEigenvalues()
Calculates eigenvalues and eigenvectors.
double getEigenvalue(short i) const
Returns the i-th Eigenvalue.
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:650
Abstract base class for different kinds of events.