Belle II Software  release-06-02-00
ContinuumSuppressionVariables.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/ContinuumSuppressionVariables.h>
10 #include <analysis/variables/ROEVariables.h>
11 #include <analysis/VariableManager/Manager.h>
12 #include <analysis/dataobjects/EventExtraInfo.h>
13 #include <analysis/dataobjects/Particle.h>
14 #include <analysis/dataobjects/ContinuumSuppression.h>
15 #include <analysis/utility/ReferenceFrame.h>
16 #include <analysis/ClusterUtility/ClusterUtils.h>
17 #include <analysis/ContinuumSuppression/FoxWolfram.h>
18 
19 #include <framework/logging/Logger.h>
20 #include <framework/datastore/StoreArray.h>
21 #include <framework/datastore/StoreObjPtr.h>
22 #include <framework/utilities/Conversion.h>
23 
24 #include <mdst/dataobjects/PIDLikelihood.h>
25 #include <mdst/dataobjects/Track.h>
26 #include <mdst/dataobjects/ECLCluster.h>
27 
28 #include <TLorentzVector.h>
29 #include <TVector3.h>
30 
31 #include <cmath>
32 
33 
34 namespace Belle2 {
39  namespace Variable {
40 
41  double R2EventLevel(const Particle*)
42  {
43  B2WARNING("The variable R2EventLevel is deprecated. Use `foxWolframR2` and ma.buildEventShape(inputListNames=[], default_cleanup=True, allMoments=False, cleoCones=True, collisionAxis=True, foxWolfram=True, harmonicMoments=True, jets=True, sphericity=True, thrust=True, checkForDuplicates=False, path=mypath)");
44 
45  std::vector<TVector3> p3_all;
46 
47  StoreArray<Track> tracks;
48  for (int i = 0; i < tracks.getEntries(); ++i) {
49  // deal with multiple possible track hypotheses in the track fit: try to
50  // retrieve the most likely from PID, maybe this fit failed so then
51  // create a particle with whatever is closest with a TrackFitResult
52  Const::ParticleType mostLikely = tracks[i]->getRelated<PIDLikelihood>()->getMostLikely();
53  const TrackFitResult* iTrack = tracks[i]->getTrackFitResultWithClosestMass(mostLikely);
54  if (iTrack == nullptr) continue;
55  if (iTrack->getChargeSign() != 0) {
56  Particle particle(tracks[i], iTrack->getParticleType());
57  PCmsLabTransform T;
58  TLorentzVector p_cms = T.rotateLabToCms() * particle.get4Vector();
59  p3_all.push_back(p_cms.Vect());
60  }
61  }
62 
63  StoreArray<ECLCluster> eclClusters;
64  for (int i = 0; i < eclClusters.getEntries(); ++i) {
65  // sum only ECLClusters which have the N1 (n photons) hypothesis
66  if (!eclClusters[i]->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
67  continue;
68 
69  ClusterUtils C;
70  TLorentzVector momECLCluster = C.Get4MomentumFromCluster(eclClusters[i], ECLCluster::EHypothesisBit::c_nPhotons);
71  if (momECLCluster == momECLCluster) {
72  if (eclClusters[i]->isNeutral()) {
73  Particle particle(eclClusters[i]);
74  PCmsLabTransform T;
75  TLorentzVector p_cms = T.rotateLabToCms() * particle.get4Vector();
76  p3_all.push_back(p_cms.Vect());
77  }
78  }
79  }
80 
81  FoxWolfram FW(p3_all);
82  FW.calculateBasicMoments();
83  return FW.getR(2);
84  }
85 
86  double R2(const Particle* particle)
87  {
88  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
89  if (!qq)
90  return std::numeric_limits<float>::quiet_NaN();
91 
92  return qq->getR2();
93  }
94 
95  double thrustBm(const Particle* particle)
96  {
97  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
98  if (!qq)
99  return std::numeric_limits<float>::quiet_NaN();
100 
101  return qq->getThrustBm();
102  }
103 
104  double thrustOm(const Particle* particle)
105  {
106  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
107  if (!qq)
108  return std::numeric_limits<float>::quiet_NaN();
109 
110  return qq->getThrustOm();
111  }
112 
113  double cosTBTO(const Particle* particle)
114  {
115  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
116  if (!qq)
117  return std::numeric_limits<float>::quiet_NaN();
118 
119  return qq->getCosTBTO();
120  }
121 
122  double cosTBz(const Particle* particle)
123  {
124  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
125  if (!qq)
126  return std::numeric_limits<float>::quiet_NaN();
127 
128  return qq->getCosTBz();
129  }
130 
131  Manager::FunctionPtr KSFWVariables(const std::vector<std::string>& arguments)
132  {
133  if (arguments.size() == 1 || arguments.size() == 2) {
134  bool useFS1 = false;
135  auto variableName = arguments[0];
136  if (arguments.size() == 2) {
137  if (arguments[1] == "FS1") {
138  useFS1 = true;
139  } else {
140  B2FATAL("Second argument in KSFWVariables can only be 'FS1' to use the KSFW moments calculated from the B final state particles! Do not include a second argument to use the default KSFW moments calculated from the B primary daughters.");
141  }
142  }
143  int index = -1;
144 
145  // all possible names
146  std::vector<std::string> names = {"mm2", "et",
147  "hso00", "hso01", "hso02", "hso03", "hso04",
148  "hso10", "hso12", "hso14",
149  "hso20", "hso22", "hso24",
150  "hoo0", "hoo1", "hoo2", "hoo3", "hoo4"
151  };
152 
153  // find the index of the name
154  for (unsigned i = 0; i < names.size(); ++i) {
155  if (variableName == names[i])
156  index = i;
157  }
158 
159  // throw helfpul error if name provided was not in allowed list
160  if (index == -1) {
161  std::string allowed = "";
162  for (auto n : names)
163  allowed += n + ", ";
164  B2FATAL("Variable name provided: " << variableName << " is not one of the allowed options. Please choose from one of:" << allowed);
165  }
166 
167  auto func = [index, useFS1](const Particle * particle) -> double {
168  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
169  if (!qq) return std::numeric_limits<double>::quiet_NaN();
170 
171  // get the KSFW moments
172  std::vector<float> ksfw = qq->getKsfwFS0();
173  if (useFS1)
174  ksfw = qq->getKsfwFS1();
175 
176  if (ksfw.size() == 0) B2FATAL("Could not find any KSFW moments");
177  return ksfw.at(index);
178  };
179  return func;
180  } else {
181  B2FATAL("Wrong number of arguments for meta function KSFWVariables. It only takes one or two arguments. The first argument must be the variable and the second can either be left blank or must be FS1 to use the KSFW moments calculated from the B final state particles.");
182  }
183  }
184 
185  Manager::FunctionPtr CleoConesCS(const std::vector<std::string>& arguments)
186  {
187  if (arguments.size() == 1 || arguments.size() == 2) {
188 
189  int coneNumber = 0;
190  try {
191  coneNumber = Belle2::convertString<int>(arguments[0]);
192  } catch (std::invalid_argument&) {
193  B2FATAL("The first argument of the CleoConeCS meta function must be an integer!");
194  }
195 
196  bool useROE = false;
197  if (arguments.size() == 2) {
198  if (arguments[1] == "ROE") {
199  useROE = true;
200  } else {
201  B2FATAL("Second argument in CleoCones can only be 'ROE' to use the CleoCones calculated from the ROE only! Do not include a second argument to use the default CleoCones calculated from all final state particles.");
202  }
203  }
204 
205  auto func = [coneNumber, useROE](const Particle * particle) -> double {
206  const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>();
207  if (!qq)
208  return std::numeric_limits<double>::quiet_NaN();
209  std::vector<float> cleoCones = qq->getCleoConesALL();
210  if (useROE)
211  cleoCones = qq->getCleoConesROE();
212  return cleoCones.at(coneNumber - 1);
213  };
214  return func;
215  } else {
216  B2FATAL("Wrong number of arguments for CleoCones function. It only takes one or two arguments. The first argument must be the cone number and the second can either be left blank or must 'ROE' to use the CleoCones calculated from all final state particles.");
217  }
218  }
219 
220  Manager::FunctionPtr transformedNetworkOutput(const std::vector<std::string>& arguments)
221  {
222  if (arguments.size() == 3) {
223  double low = 0;
224  double high = 0;
225  try {
226  low = Belle2::convertString<double>(arguments[1]);
227  high = Belle2::convertString<double>(arguments[2]);
228  } catch (std::invalid_argument&) {
229  B2FATAL("Second and third argument of transformedNetworkOutput meta function must be doubles!");
230  }
231 
232  auto extraInfoName = arguments[0];
233  auto func = [extraInfoName, low, high](const Particle * particle) -> double {
234  if (particle == nullptr)
235  {
236  StoreObjPtr<EventExtraInfo> eventExtraInfo;
237  if (eventExtraInfo->hasExtraInfo(extraInfoName)) {
238  return eventExtraInfo->getExtraInfo(extraInfoName);
239  } else {
240  return std::numeric_limits<double>::quiet_NaN();
241  }
242  }
243  if (particle->hasExtraInfo(extraInfoName))
244  {
245  return std::log(((particle->getExtraInfo(extraInfoName)) - low) / (high - (particle->getExtraInfo(extraInfoName))));
246  } else {
247  return std::numeric_limits<double>::quiet_NaN();
248  }
249  };
250  return func;
251  } else {
252  B2FATAL("Wrong number of arguments for meta function transformedNetworkOutput");
253  }
254  }
255 
256  Manager::FunctionPtr useBThrustFrame(const std::vector<std::string>& arguments)
257  {
258  if (arguments.size() == 2) {
259  auto variableName = arguments[0];
260  std::string mode = arguments[1];
261 
262  const bool modeisSignal = mode == "Signal";
263  const bool modeisAuto = mode == "Auto";
264 
265  if (not modeisSignal and (mode != "ROE") and not modeisAuto)
266  B2FATAL("Second argument in useBThrustFrame can only be 'Signal', 'ROE' or 'Auto'. Your argument was " + mode);
267 
268  const Variable::Manager::Var* var = Manager::Instance().getVariable(variableName);
269 
270  auto func = [var, modeisSignal, modeisAuto](const Particle * particle) -> double {
271  StoreObjPtr<RestOfEvent> roe("RestOfEvent");
272  const Particle* Bparticle = roe->getRelated<Particle>();
273  const ContinuumSuppression* qq = Bparticle->getRelatedTo<ContinuumSuppression>();
274  if (!qq)
275  return std::numeric_limits<double>::quiet_NaN();
276  double isinROE = isInRestOfEvent(particle);
277  TVector3 newZ;
278  if (modeisSignal or (modeisAuto and isinROE < 0.5))
279  newZ = qq->getThrustB();
280  else
281  newZ = qq->getThrustO();
282 
283  TVector3 newY(0, 0, 0);
284  if (newZ(2) == 0 and newZ(1) == 0)
285  newY(0) = 1;
286  else{
287  newY(1) = newZ(2);
288  newY(2) = -newZ(1);
289  }
290  TVector3 newX = newY.Cross(newZ);
291 
292  UseReferenceFrame<CMSRotationFrame> signalframe(newX, newY, newZ);
293 
294  return var->function(particle);
295  };
296  return func;
297  } else {
298  B2FATAL("Wrong number of arguments for meta function useBThrustFrame. It only takes two arguments. The first argument must be the variable and the second can either be .");
299  }
300  }
301 
302 
303  VARIABLE_GROUP("Continuum Suppression");
304  REGISTER_VARIABLE("R2EventLevel", R2EventLevel,
305  "[Eventbased] Event-Level Reduced Fox-Wolfram moment R2.");
306  MAKE_DEPRECATED("R2EventLevel", false, "release-05-00-00", R"DOC(
307  The same value can be calculated with the Event Shape module, see :b2:var:`foxWolframR`.)DOC");
308  REGISTER_VARIABLE("R2" , R2 , R"DOC(
309 Returns reduced Fox-Wolfram R2, defined as ratio of the i-th to the 0-th order Fox Wolfram moments.
310 
311 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
312 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
313 )DOC");
314  REGISTER_VARIABLE("thrustBm" , thrustBm , R"DOC(
315 Returns magnitude of the signal B thrust axis.
316 
317 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
318 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
319 )DOC");
320  REGISTER_VARIABLE("thrustOm" , thrustOm , R"DOC(
321 Returns magnitude of the ROE thrust axis.
322 
323 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
324 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
325 )DOC");
326  REGISTER_VARIABLE("cosTBTO" , cosTBTO , R"DOC(
327 Returns cosine of angle between thrust axis of the signal B and thrust axis of ROE.
328 
329 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
330 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
331 )DOC");
332  REGISTER_VARIABLE("cosTBz" , cosTBz , R"DOC(
333 Returns cosine of angle between thrust axis of the signal B and z-axis.
334 
335 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
336 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
337 )DOC");
338  REGISTER_VARIABLE("KSFWVariables(variable,string)", KSFWVariables, R"DOC(
339 Returns variable et, mm2, or one of the 16 KSFW moments. If only the ``variable`` argument is specified, the KSFW moment calculated from the B primary daughters is returned.
340 If string is set to ``FS1``, the KSFW moment calculated from the B final state daughters is returned.
341 Allowed input values for ``variable`` argument are the following:
342 
343 * mm2, et
344 * hso00, hso01, hso02, hso03, hso04
345 * hso10, hso12, hso14
346 * hso20, hso22, hso24
347 * hoo0, hoo1, hoo2, hoo3, hoo4.
348 
349 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
350 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
351 )DOC");
352 
353  REGISTER_VARIABLE("CleoConeCS(integer,string)", CleoConesCS, R"DOC(
354 Returns i-th cleo cones from the continuum suppression. The allowed inputs for ``integer`` argument are integers from *1* to *9*.
355 If only the ``integer`` argument is specified, the CleoCones are calculated from all final state particles.
356 The ``string`` argument is optional and the only allowed input value is 'ROE', which sets the CleoCones to be calculated only from ROE particles.
357 
358 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
359 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
360 )DOC");
361 
362  REGISTER_VARIABLE("transformedNetworkOutput(name, low, high)", transformedNetworkOutput, R"DOC(
363 Transforms the network output :math:`C \to C'` via: :math:`C'=\operatorname{log}((C-\mathrm{low})/(\mathrm{high}-C))`.
364 The arguments of the metavariable are the following:
365 
366 * ``name`` is the `extraInfo` name, where the network output :math:`C` has been stored. If particle is not specified, event `extraInfo` is used instead;
367 * ``low``, ``high`` are floating point numbers.
368 
369 Returns NaN, if the `extraInfo` has not been found.
370 )DOC");
371 
372  REGISTER_VARIABLE("useBThrustFrame(variable, mode)", useBThrustFrame, R"DOC(
373 Returns the variable with respect to rotated coordinates, in which z lies on the specified thrust axis.
374 If mode is set to ``Signal`` it will use the thrust axis of the reconstructed B candidate, if mode is set to ROE it will use the ROE thrust axis.
375 If mode is set to ``Auto`` the function use the thrust axis based on Rest Of Event (ROE) particles.
376 Like :b2:var:`isInRestOfEvent`, one has to use this metavariable in ROE loop.
377 
378 .. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
379 .. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
380 )DOC");
381 
382  }
384 }
@ c_nPhotons
CR is split into n photons (N1)
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:31
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:25
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
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
Definition: Manager.h:345
Abstract base class for different kinds of events.