Belle II Software  release-06-02-00
Thrust.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 
10 // //
11 // Thrust.cc //
12 // //
13 // calculation of the thrust quantity //
14 // from a vector of 3D momenta. //
15 // Returns the thrust axes (vector). //
16 // {cc,h} //
17 // Brandt, S., Dahmen, H.D. Axes and //
18 // scalar measures of two-jet and //
19 // three-jet events. Z. Phys. C - //
20 // Particles and Fields 1, 61–70 //
21 // (1979). //
22 // https://doi.org/10.1007/BF01450381 //
23 // http://home.thep.lu.se/~torbjorn/ppp2011/lec8.pdf
24 // https://home.fnal.gov/~mrenna/lu_update/lutp0613man2/node235.html
25 // //
26 // Last modified 2021 March 15th //
28 
29 
30 /* ******************** NOTES ******************** *
31  * INPUT : std::vector<TVector3> : momenta *
32  * OUTPUT: TVector3 : thrust axis *
33  * *
34  * = and /= operators not defined for TVector3 obj *
35  * [ TVector3 x *= 1 / scalar ] better alternative *
36  * *
37  * Thrust Axis defined as: *
38  * thrust_axis = ( vec{n} ÷ ||n|| ) * thrust *
39  * *
40  * Thrust (Scalar) defined as: *
41  * Σ(p_i · vec{n}) *
42  * thrust = max( ÷ ) *
43  * Σ(||p_i||) * ||n|| *
44  * *
45  * *********************************************** */
46 
47 /* *************************** STEPS *************************** *
48  * Initialization: *
49  * 1. Initialize all variables *
50  * 2. Parse momenta vector to compute magnitude Σ(||p_i||) *
51  * *
52  * Pick a thrust axis and optimize (max Σ(p_i · vec{n})): *
53  * 3. Define p_k as thrust axis (initial conditions) *
54  * 4. Define p_j = Sum (± p_i) as thrust axis (trial) *
55  * - note: ± = to sign of (p_i · p_k) *
56  * 5. Check if ( p_i · p_j ) * ( p_i · p_k ) < 0 for all p_i *
57  * 6. While True, p_k = p_j and repeat 4 -> 5, else see go to 7 *
58  * 7. Compute thrust associated to selected trial axis *
59  * *
60  * Find best local Thrust (scalar) maxima possible: *
61  * 8. Keep trial axis as thrust axis if trial > base thrust *
62  * 9. Repeat from 3 -> 8 for each momentum in momenta vector *
63  * *
64  * Return thrust axis associated to best Thrust: *
65  * 10. Multiply normalized thrust axis by Thrust (<= 1) *
66  * *
67  * ************************************************************* */
68 
69 #include <analysis/ContinuumSuppression/Thrust.h>
70 
71 using namespace Belle2;
72 
73 
74 TVector3 Thrust::calculateThrust(const std::vector<TVector3>& momenta)
75 {
76 
77  /* STEP 1: Initialization of Variables */
78  TVector3 thrust_axis, trial_axis, base_axis;
79  auto end = momenta.end();
80  auto begin = momenta.begin();
81  decltype(begin) itr;
82 
83  double sum_magnitude_mom = 0.;
84  double thrust = 0.;
85 
86  /*
87  STEP 2: Parse momenta vector to compute magnitude Σ(||p_i||)
88  */
89 
90  for (auto const& momentum : momenta)
91  sum_magnitude_mom += momentum.Mag();
92 
93  /*
94  STEP 3: For each momentum in momenta vector,
95  use momentum as initial axis to optimize
96  */
97 
98  for (auto const& mom : momenta) {
99  // By convention, thrust axis in same direction as Z axis
100  trial_axis = (mom.z() >= 0.) ? TVector3(mom) : TVector3(-mom);
101 
102  // Normalize if magnitude != 0
103  if (trial_axis.Mag() != 0.) trial_axis *= 1. / trial_axis.Mag();
104 
105  /*
106  STEP 4: Store the previous trial axis as a base axis and initialize
107  a new trial axis as the Z-aligned sum of the momentum vectors
108  */
109 
110  itr = begin;
111  while (itr != end) {
112  base_axis = trial_axis;
113  trial_axis = TVector3();
114 
115  // Z-alignment of momenta and addition to trial axis
116  for (auto const& momentum : momenta)
117  trial_axis += (momentum.Dot(base_axis) >= 0.) ? \
118  TVector3(momentum) : TVector3(-momentum);
119 
120  /*
121  STEP 5: Check ( p_i · trial_axis ) * ( p_i · base_axis ) < 0 ∀ p_i
122  */
123 
124  for (itr = begin; itr != end; itr++)
125  if ((*itr).Dot(trial_axis) * (*itr).Dot(base_axis) < 0.) break;
126 
127  /*
128  STEP 6: While condition True:
129  base_axis = trial_axis
130  repeat STEP 4 and STEP 5;
131  else:
132  go to STEP 7 (while from STEP 4 is done)
133  */
134  }
135 
136  double trial_mag(trial_axis.Mag()); // pre-compute
137  // trial_axis *= (1. / trial_axis.Mag());
138 
139  /*
140  STEP 7: Compute the thrust associated to the selected trial axis
141  Σ(p_i · vec{n})
142  thrust = max( ÷ )
143  Σ(||p_i||) * ||n||
144  */
145  double trial_thrust(0.);
146  for (auto const& momentum : momenta)
147  trial_thrust += std::fabs(momentum.Dot(trial_axis));
148 
149  trial_thrust /= (sum_magnitude_mom * trial_mag);
150  // trial_thrust /= sum_magnitude_mom;
151 
152  /*
153  STEP 8: Keep trial axis as thrust axis better
154  */
155  if (trial_thrust > thrust) {
156  thrust = trial_thrust;
157  thrust_axis = trial_axis * (1. / trial_mag);
158  // thrust_axis = trial_axis;
159  }
160 
161  /*
162  STEP 9: Repeat from STEP 3 to STEP 8 (select base axis)
163  to avoid falling in local maxima
164  */
165  }
166 
167  /*
168  STEP 10: Multiply normalized thrust axis by Thrust (<= 1)
169  */
170  thrust_axis *= thrust;
171  return thrust_axis;
172 }
static TVector3 calculateThrust(const std::vector< TVector3 > &momenta)
calculates the thrust axis
Definition: Thrust.cc:74
Abstract base class for different kinds of events.