Belle II Software development
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
11#include <analysis/variables/ROEVariables.h>
12#include <analysis/VariableManager/Manager.h>
13#include <framework/dataobjects/EventExtraInfo.h>
14#include <analysis/dataobjects/Particle.h>
15#include <analysis/dataobjects/ContinuumSuppression.h>
16#include <analysis/utility/ReferenceFrame.h>
17
18#include <framework/logging/Logger.h>
19#include <framework/datastore/StoreObjPtr.h>
20#include <framework/utilities/Conversion.h>
21
22#include <cmath>
23
24
25namespace Belle2 {
30 namespace Variable {
31
32 Manager::FunctionPtr R2WithMask(const std::vector<std::string>& arguments)
33 {
34 if (arguments.size() != 1)
35 B2FATAL("An empty argument is not allowed for the variable R2."
36 "Either provide no argument or a valid mask name.");
37 std::string maskName = arguments[0];
38 auto func = [maskName](const Particle * particle) -> double {
39 const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
40 if (!qq)
41 return Const::doubleNaN;
42
43 return qq->getR2();
44 };
45 return func;
46 }
47
48 double R2(const Particle* particle)
49 {
50 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
51 if (continuumSuppressionRelations.size() == 1) {
52 const ContinuumSuppression* qq = continuumSuppressionRelations[0];
53 return qq->getR2();
54 } else {
55 if (continuumSuppressionRelations.size() > 1) {
56 B2ERROR("The return value of R2 is ambiguous. Please provide the mask name as argument.");
57 }
58 return Const::doubleNaN;
59 }
60 }
61
62 Manager::FunctionPtr thrustBmWithMask(const std::vector<std::string>& arguments)
63 {
64 if (arguments.size() != 1)
65 B2FATAL("An empty argument is not allowed for the variable thrustBm."
66 "Either provide no argument or a valid mask name.");
67 std::string maskName = arguments[0];
68 auto func = [maskName](const Particle * particle) -> double {
69 const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
70 if (!qq)
71 return Const::doubleNaN;
72
73 return qq->getThrustBm();
74 };
75 return func;
76 }
77
78 double thrustBm(const Particle* particle)
79 {
80 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
81 if (continuumSuppressionRelations.size() == 1) {
82 const ContinuumSuppression* qq = continuumSuppressionRelations[0];
83 return qq->getThrustBm();
84 } else {
85 if (continuumSuppressionRelations.size() > 1) {
86 B2ERROR("The return value of thrustBm is ambiguous. Please provide the mask name as argument.");
87 }
88 return Const::doubleNaN;
89 }
90 }
91
92 Manager::FunctionPtr thrustOmWithMask(const std::vector<std::string>& arguments)
93 {
94 if (arguments.size() != 1)
95 B2FATAL("An empty argument is not allowed for the variable thrustOm."
96 "Either provide no argument or a valid mask name.");
97 std::string maskName = arguments[0];
98 auto func = [maskName](const Particle * particle) -> double {
99 const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
100 if (!qq)
101 return Const::doubleNaN;
102
103 return qq->getThrustOm();
104 };
105 return func;
106 }
107
108 double thrustOm(const Particle* particle)
109 {
110 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
111 if (continuumSuppressionRelations.size() == 1) {
112 const ContinuumSuppression* qq = continuumSuppressionRelations[0];
113 return qq->getThrustOm();
114 } else {
115 if (continuumSuppressionRelations.size() > 1) {
116 B2ERROR("The return value of thrustOm is ambiguous. Please provide the mask name as argument.");
117 }
118 return Const::doubleNaN;
119 }
120 }
121
122 Manager::FunctionPtr cosTBTOWithMask(const std::vector<std::string>& arguments)
123 {
124 if (arguments.size() != 1)
125 B2FATAL("An empty argument is not allowed for the variable cosTBTO."
126 "Either provide no argument or a valid mask name.");
127 std::string maskName = arguments[0];
128 auto func = [maskName](const Particle * particle) -> double {
129 const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
130 if (!qq)
131 return Const::doubleNaN;
132
133 return qq->getCosTBTO();
134 };
135 return func;
136 }
137
138 double cosTBTO(const Particle* particle)
139 {
140 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
141 if (continuumSuppressionRelations.size() == 1) {
142 const ContinuumSuppression* qq = continuumSuppressionRelations[0];
143 return qq->getCosTBTO();
144 } else {
145 if (continuumSuppressionRelations.size() > 1) {
146 B2ERROR("The return value of cosTBTO is ambiguous. Please provide the mask name as argument.");
147 }
148 return Const::doubleNaN;
149 }
150 }
151
152 Manager::FunctionPtr cosTBzWithMask(const std::vector<std::string>& arguments)
153 {
154 if (arguments.size() != 1)
155 B2FATAL("An empty argument is not allowed for the variable cosTBz."
156 "Either provide no argument or a valid mask name.");
157 std::string maskName = arguments[0];
158 auto func = [maskName](const Particle * particle) -> double {
159 const ContinuumSuppression* qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
160 if (!qq)
161 return Const::doubleNaN;
162
163 return qq->getCosTBz();
164 };
165 return func;
166 }
167
168 double cosTBz(const Particle* particle)
169 {
170 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
171 if (continuumSuppressionRelations.size() == 1) {
172 const ContinuumSuppression* qq = continuumSuppressionRelations[0];
173 return qq->getCosTBz();
174 } else {
175 if (continuumSuppressionRelations.size() > 1) {
176 B2ERROR("The return value of cosTBz is ambiguous. Please provide the mask name as argument.");
177 }
178 return Const::doubleNaN;
179 }
180 }
181
182 Manager::FunctionPtr KSFWVariables(const std::vector<std::string>& arguments)
183 {
184 if (arguments.size() > 0 && arguments.size() < 4) {
185 bool useFS1 = false;
186 auto variableName = arguments[0];
187 std::string maskName = "";
188 if (arguments.size() >= 2) {
189 if (arguments[1] == "FS1") {
190 useFS1 = true;
191 } else {
192 maskName = arguments[1];
193 }
194 if (arguments.size() == 3) {
195 maskName = arguments[2];
196 if (maskName == "FS1") {
197 B2ERROR("It looks like you provided the arguments for KSFWVariables in the wrong order."
198 "If you want to use the KSFW moments calculated from the B final state particles, the second argument has to be 'FS1'."
199 "The third argument would then have to be the ROE mask name.");
200 }
201 }
202 }
203 int index = -1;
204
205 // all possible names
206 std::vector<std::string> names = {"mm2", "et",
207 "hso00", "hso01", "hso02", "hso03", "hso04",
208 "hso10", "hso12", "hso14",
209 "hso20", "hso22", "hso24",
210 "hoo0", "hoo1", "hoo2", "hoo3", "hoo4"
211 };
212
213 // find the index of the name
214 for (unsigned i = 0; i < names.size(); ++i) {
215 if (variableName == names[i])
216 index = i;
217 }
218
219 // throw helpful error if name provided was not in allowed list
220 if (index == -1) {
221 std::string allowed = "";
222 for (auto n : names)
223 allowed += n + ", ";
224 B2FATAL("Variable name provided: " << variableName << " is not one of the allowed options. Please choose from one of:" << allowed);
225 }
226
227 auto func = [index, useFS1, maskName](const Particle * particle) -> double {
228 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
229 ContinuumSuppression* qq = nullptr;
230 if (maskName.empty())
231 {
232 if (continuumSuppressionRelations.size() == 1) {
233 qq = continuumSuppressionRelations[0];
234 } else if (continuumSuppressionRelations.size() > 1) {
235 B2ERROR("The return value of KSFWVariables is ambiguous. Please provide the mask name as argument.");
236 }
237 } else
238 {
239 qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
240 }
241 if (!qq) return Const::doubleNaN;
242
243 // get the KSFW moments
244 std::vector<float> ksfw = qq->getKsfwFS0();
245 if (useFS1)
246 ksfw = qq->getKsfwFS1();
247
248 if (ksfw.size() == 0) B2FATAL("Could not find any KSFW moments");
249 return ksfw.at(index);
250 };
251 return func;
252 } else {
253 B2FATAL("Wrong number of arguments for meta function KSFWVariables. It only takes between one and three arguments."
254 " The first argument must be the variable. If you want to use the KSFW moments calculated from the B final state particles, set 'FS1' as second argument."
255 " You can also provide the ROE mask name as second or third argument.");
256 }
257 }
258
259 Manager::FunctionPtr CleoConesCS(const std::vector<std::string>& arguments)
260 {
261 if (arguments.size() > 0 && arguments.size() < 4) {
262
263 int coneNumber = 0;
264 try {
265 coneNumber = Belle2::convertString<int>(arguments[0]);
266 } catch (std::invalid_argument&) {
267 B2FATAL("The first argument of the CleoConeCS meta function must be an integer!");
268 }
269
270 bool useROE = false;
271 std::string maskName = "";
272 if (arguments.size() >= 2) {
273 if (arguments[1] == "ROE") {
274 useROE = true;
275 } else {
276 maskName = arguments[1];
277 }
278 if (arguments.size() == 3) {
279 maskName = arguments[2];
280 if (maskName == "ROE") {
281 B2ERROR("It looks like you provided the arguments for CleoConeCS in the wrong order."
282 "If you want to use the CleoCones calculated from all final state particles, the second argument has to be 'ROE'."
283 "The third argument would then have to be the ROE mask name.");
284 }
285 }
286 }
287
288 auto func = [coneNumber, useROE, maskName](const Particle * particle) -> double {
289 RelationVector<ContinuumSuppression> continuumSuppressionRelations = particle->getRelationsTo<ContinuumSuppression>("ALL");
290 ContinuumSuppression* qq = nullptr;
291 if (maskName.empty())
292 {
293 if (continuumSuppressionRelations.size() == 1) {
294 qq = continuumSuppressionRelations[0];
295 } else if (continuumSuppressionRelations.size() > 1) {
296 B2ERROR("The return value of CleoConeCS is ambiguous. Please provide the mask name as argument.");
297 }
298 } else
299 {
300 qq = particle->getRelatedTo<ContinuumSuppression>(maskName);
301 }
302 if (!qq)
303 return Const::doubleNaN;
304
305 std::vector<float> cleoCones = qq->getCleoConesALL();
306 if (useROE)
307 cleoCones = qq->getCleoConesROE();
308 return cleoCones.at(coneNumber - 1);
309 };
310 return func;
311 } else {
312 B2FATAL("Wrong number of arguments for CleoConeCS function. It only takes between one and three arguments."
313 "The first argument must be the cone number. If you want to use the CleoCones calculated from all final state particles, set 'ROE' as second argument."
314 "You can also provide the ROE mask name as second or third argument.");
315 }
316 }
317
318 Manager::FunctionPtr transformedNetworkOutput(const std::vector<std::string>& arguments)
319 {
320 if (arguments.size() == 3) {
321 double low = 0;
322 double high = 0;
323 try {
324 low = Belle2::convertString<double>(arguments[1]);
325 high = Belle2::convertString<double>(arguments[2]);
326 } catch (std::invalid_argument&) {
327 B2FATAL("Second and third argument of transformedNetworkOutput meta function must be doubles!");
328 }
329
330 auto extraInfoName = arguments[0];
331 auto func = [extraInfoName, low, high](const Particle * particle) -> double {
332 if (particle == nullptr)
333 {
334 StoreObjPtr<EventExtraInfo> eventExtraInfo;
335 if (eventExtraInfo->hasExtraInfo(extraInfoName)) {
336 return eventExtraInfo->getExtraInfo(extraInfoName);
337 } else {
338 return Const::doubleNaN;
339 }
340 }
341 if (particle->hasExtraInfo(extraInfoName))
342 {
343 return std::log(((particle->getExtraInfo(extraInfoName)) - low) / (high - (particle->getExtraInfo(extraInfoName))));
344 } else
345 {
346 return Const::doubleNaN;
347 }
348 };
349 return func;
350 } else {
351 B2FATAL("Wrong number of arguments for meta function transformedNetworkOutput");
352 }
353 }
354
355 Manager::FunctionPtr useBThrustFrame(const std::vector<std::string>& arguments)
356 {
357 if (arguments.size() == 2 || arguments.size() == 3) {
358 auto variableName = arguments[0];
359 std::string mode = arguments[1];
360
361 const bool modeisSignal = mode == "Signal";
362 const bool modeisAuto = mode == "Auto";
363
364 if (not modeisSignal and (mode != "ROE") and not modeisAuto)
365 B2FATAL("Second argument in useBThrustFrame can only be 'Signal', 'ROE' or 'Auto'. Your argument was " + mode);
366
367 const Variable::Manager::Var* var = Manager::Instance().getVariable(variableName);
368
369 std::string maskName = arguments.size() == 3 ? arguments[2] : "";
370
371 auto func = [var, modeisSignal, modeisAuto, maskName](const Particle * particle) -> double {
372 StoreObjPtr<RestOfEvent> roe("RestOfEvent");
373 const Particle* Bparticle = roe->getRelatedFrom<Particle>();
374 RelationVector<ContinuumSuppression> continuumSuppressionRelations = Bparticle->getRelationsTo<ContinuumSuppression>("ALL");
375 ContinuumSuppression* qq = nullptr;
376 if (maskName.empty())
377 {
378 if (continuumSuppressionRelations.size() == 1) {
379 qq = continuumSuppressionRelations[0];
380 } else if (continuumSuppressionRelations.size() > 1) {
381 B2ERROR("The return value of useBThrustFrame is ambiguous. Please provide the mask name as argument.");
382 }
383 } else
384 {
385 qq = Bparticle->getRelatedTo<ContinuumSuppression>(maskName);
386 }
387 if (!qq)
388 return Const::doubleNaN;
389
390 bool isinROE = isInRestOfEvent(particle);
391 ROOT::Math::XYZVector newZ;
392 if (modeisSignal or (modeisAuto and isinROE))
393 newZ = qq->getThrustB();
394 else
395 newZ = qq->getThrustO();
396
397 ROOT::Math::XYZVector newY(0, 0, 0);
398 if (newZ.Z() == 0 and newZ.Y() == 0)
399 newY.SetX(1);
400 else
401 {
402 newY.SetY(newZ.Z());
403 newY.SetZ(-newZ.Y());
404 }
405 ROOT::Math::XYZVector newX = newY.Cross(newZ);
406
407 UseReferenceFrame<CMSRotationFrame> signalframe(newX, newY, newZ);
408
409 return std::get<double>(var->function(particle));
410 };
411 return func;
412 } else {
413 B2FATAL("Wrong number of arguments for meta function useBThrustFrame. It only takes two or three arguments. The first argument must be the variable."
414 "The second can either be 'Signal', 'ROE', or 'Auto'."
415 "The third argument is optional (as long as the ContinuumSuppression was built only once) and can define a specific ROE mask name.");
416 }
417 }
418
419
420 VARIABLE_GROUP("Continuum Suppression");
421 REGISTER_METAVARIABLE("R2(maskname)", R2WithMask, R"DOC(
422Returns reduced Fox-Wolfram R2, defined as ratio of the i-th to the 0-th order Fox Wolfram moments.
423
424.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
425.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
426)DOC", Manager::VariableDataType::c_double);
427 REGISTER_VARIABLE("R2", R2 , R"DOC(
428Returns reduced Fox-Wolfram R2, defined as ratio of the i-th to the 0-th order Fox Wolfram moments.
429
430.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
431.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
432:noindex:
433)DOC");
434 REGISTER_METAVARIABLE("thrustBm(maskname)", thrustBmWithMask, R"DOC(
435Returns magnitude of the signal B thrust axis.
436
437.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
438.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
439)DOC", Manager::VariableDataType::c_double);
440 REGISTER_VARIABLE("thrustBm", thrustBm, R"DOC(
441Returns magnitude of the signal B thrust axis.
442
443.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
444.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
445:noindex:
446)DOC");
447 REGISTER_METAVARIABLE("thrustOm(maskname)", thrustOmWithMask, R"DOC(
448Returns magnitude of the ROE thrust axis.
449
450.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
451.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
452)DOC", Manager::VariableDataType::c_double);
453 REGISTER_VARIABLE("thrustOm", thrustOm, R"DOC(
454Returns magnitude of the ROE thrust axis.
455
456.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
457.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
458:noindex:
459)DOC");
460 REGISTER_METAVARIABLE("cosTBTO(maskname)", cosTBTOWithMask, R"DOC(
461Returns cosine of angle between thrust axis of the signal B and thrust axis of ROE.
462
463.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
464.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
465)DOC", Manager::VariableDataType::c_double);
466 REGISTER_VARIABLE("cosTBTO", cosTBTO, R"DOC(
467Returns cosine of angle between thrust axis of the signal B and thrust axis of ROE.
468
469.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
470.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
471:noindex:
472)DOC");
473 REGISTER_METAVARIABLE("cosTBz(maskname)", cosTBzWithMask, R"DOC(
474Returns cosine of angle between thrust axis of the signal B and z-axis.
475
476.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
477.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
478)DOC", Manager::VariableDataType::c_double);
479 REGISTER_VARIABLE("cosTBz", cosTBz, R"DOC(
480Returns cosine of angle between thrust axis of the signal B and z-axis.
481
482.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
483.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
484:noindex:
485)DOC");
486 REGISTER_METAVARIABLE("KSFWVariables(variable[, string, string])", KSFWVariables, R"DOC(
487Returns variable et in ``GeV/c``, mm2 in (GeV/c^2)^2, or one of the 16 KSFW moments.
488The second and third arguments are optional unless you have created multiple instances of the ContinuumSuppression with different ROE masks.
489In that case the desired ROE mask name must be provided as well.
490If the second argument is set to 'FS1', the KSFW moment is calculated from the B final state daughters.
491Otherwise, the KSFW moment is calculated from the B primary daughters.
492The ROE mask name is then either the second or the third argument and must not be called 'FS1'.
493Allowed input values for ``variable`` argument are the following:
494
495* mm2, et
496* hso00, hso01, hso02, hso03, hso04
497* hso10, hso12, hso14
498* hso20, hso22, hso24
499* hoo0, hoo1, hoo2, hoo3, hoo4.
500
501.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
502.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
503)DOC", Manager::VariableDataType::c_double);
504
505 REGISTER_METAVARIABLE("CleoConeCS(integer[, string, string])", CleoConesCS, R"DOC(
506Returns i-th cleo cones from the continuum suppression. The allowed inputs for the ``integer`` argument are integers from *1* to *9*.
507The second and third arguments are optional unless you have created multiple instances of the ContinuumSuppression with different ROE masks.
508In that case the desired ROE mask name must be provided as well.
509If the second argument is set to 'ROE', the CleoCones are calculated only from ROE particles.
510Otherwise, the CleoCones are calculated from all final state particles.
511The ROE mask name is then either the second or the third argument and must not be called 'ROE'. The unit of the CleoConeCS is ``GeV/c``.
512
513.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
514.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
515)DOC", Manager::VariableDataType::c_double);
516
517 REGISTER_METAVARIABLE("transformedNetworkOutput(name, low, high)", transformedNetworkOutput, R"DOC(
518Transforms the network output :math:`C \to C'` via: :math:`C'=\operatorname{log}((C-\mathrm{low})/(\mathrm{high}-C))`.
519The arguments of the metavariable are the following:
520
521* ``name`` is the `extraInfo` name, where the network output :math:`C` has been stored. If particle is not specified, event `extraInfo` is used instead;
522* ``low``, ``high`` are floating point numbers.
523
524Returns NaN, if the `extraInfo` has not been found.
525)DOC", Manager::VariableDataType::c_double);
526
527 REGISTER_METAVARIABLE("useBThrustFrame(variable, mode)", useBThrustFrame, R"DOC(
528Returns the variable with respect to rotated coordinates, in which z lies on the specified thrust axis.
529If 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.
530If mode is set to ``Auto`` the function use the thrust axis based on Rest Of Event (ROE) particles.
531Like :b2:var:`isInRestOfEvent`, one has to use this metavariable in ROE loop.
532
533.. warning:: You have to run the Continuum Suppression builder module for this variable to be meaningful.
534.. seealso:: :ref:`analysis_continuumsuppression` and `buildContinuumSuppression`.
535)DOC", Manager::VariableDataType::c_double);
536
537 }
539}
static const double doubleNaN
quiet_NaN
Definition: Const.h:703
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
Definition: Manager.h:112
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:58
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:26
Abstract base class for different kinds of events.