Belle II Software light-2607-kasei
TriggerVariables.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/TriggerVariables.h>
11
12#include <analysis/dataobjects/Particle.h>
13
14// trigger dataobjects
15#include <mdst/dataobjects/TRGSummary.h>
16#include <mdst/dataobjects/SoftwareTriggerResult.h>
17
18// trigger dbobjects
19#include <mdst/dbobjects/TRGGDLDBFTDLBits.h>
20#include <mdst/dbobjects/TRGGDLDBPrescales.h>
21
22// HLT dbobjects
23#include <mdst/dbobjects/DBRepresentationOfSoftwareTriggerCut.h>
24
25// framework
26#include <framework/logging/Logger.h>
27#include <framework/datastore/StoreObjPtr.h>
28#include <framework/database/DBObjPtr.h>
29
30// boost
31#include <boost/algorithm/string.hpp>
32
33// C++
34#include <limits>
35#include <stdexcept>
36
37namespace Belle2 {
42 namespace {
57 std::string fullFormatIdentifier(const std::string& identifier)
58 {
59 std::string out = identifier;
60 boost::replace_all(out, " ", "&");
61 if (identifier.substr(0, 21) != "software_trigger_cut&")
62 out = "software_trigger_cut&" + out;
63 return out;
64 }
65
70 double extractSoftwareTriggerResultImplementation(bool nonPrescaled, const std::string& triggerIdentifier, const Particle*)
71 {
72 // get trigger result object
74 if (!swtr)
75 return Const::doubleNaN;
76
77 // check that the trigger ID provided by the user exists in the SWTR
79 try {
80 if (nonPrescaled) {
81 swtcr = swtr->getNonPrescaledResult(fullFormatIdentifier(triggerIdentifier));
82 } else {
83 swtcr = swtr->getResult(fullFormatIdentifier(triggerIdentifier));
84 }
85 } catch (const std::out_of_range&) {
86 // then the trigger identifier is wrong -- silently return nan
87 return Const::doubleNaN;
88 }
89 return double(swtcr); // see mdst/dataobjects/include/SoftwareTriggerResult.h
90 };
91 }
92
93 namespace Variable {
94
95 double L1Trigger(const Particle*)
96 {
97 StoreObjPtr<TRGSummary> trg;
98 if (!trg)
99 return Const::doubleNaN;
100 return trg->test();
101 }
102
103 Manager::FunctionPtr L1PSNM(const std::vector<std::string>& arguments)
104 {
105 if (arguments.size() == 1) {
106 auto name = arguments[0];
107 auto func = [name](const Particle*) -> double {
108 StoreObjPtr<TRGSummary> trg;
109 if (!trg)
110 return Const::doubleNaN;
111 try
112 {
113 return trg->testPsnm(name);
114 } catch (const std::exception&)
115 {
116 // Something went wrong, return NaN.
117 return Const::doubleNaN;
118 }
119 };
120 return func;
121 } else {
122 B2FATAL("Wrong number of arguments for L1PSNM function. The only argument must be the name of the PSNM trigger bit.");
123 }
124 }
125
126 double L1PSNMBit(const Particle*, const std::vector<double>& arguments)
127 {
128 if (arguments.size() == 1) {
129 StoreObjPtr<TRGSummary> trg;
130 if (!trg)
131 return Const::doubleNaN;
132 try {
133 int testBit = std::lround(arguments[0]);
134 return trg->testPsnm(testBit);
135 } catch (const std::exception&) {
136 // Something went wrong, return NaN.
137 return Const::doubleNaN;
138 }
139 } else {
140 B2FATAL("Wrong number of arguments for L1PSNMBit function. The only argument must be the number of the PSNM trigger bit.");
141 }
142 }
143
144 Manager::FunctionPtr L1FTDL(const std::vector<std::string>& arguments)
145 {
146 if (arguments.size() == 1) {
147 auto name = arguments[0];
148 auto func = [name](const Particle*) -> double {
149 StoreObjPtr<TRGSummary> trg;
150 if (!trg)
151 return Const::doubleNaN;
152 try
153 {
154 return trg->testFtdl(name);
155 } catch (const std::exception&)
156 {
157 // Something went wrong, return NaN.
158 return Const::doubleNaN;
159 }
160 };
161 return func;
162 } else {
163 B2FATAL("Wrong number of arguments for L1FTDL function. The only argument must be the name of the FTDL trigger bit.");
164 }
165 }
166
167 double L1FTDLBit(const Particle*, const std::vector<double>& arguments)
168 {
169 if (arguments.size() == 1) {
170 StoreObjPtr<TRGSummary> trg;
171 if (!trg)
172 return Const::doubleNaN;
173 try {
174 int testBit = std::lround(arguments[0]);
175 return trg->testFtdl(testBit);
176 } catch (const std::exception&) {
177 // Something went wrong, return NaN.
178 return Const::doubleNaN;
179 }
180 } else {
181 B2FATAL("Wrong number of arguments for L1FTDLBit function. The only argument must be the number of the FTDL trigger bit.");
182 }
183 }
184
185 Manager::FunctionPtr L1Input(const std::vector<std::string>& arguments)
186 {
187 if (arguments.size() == 1) {
188 auto name = arguments[0];
189 auto func = [name](const Particle*) -> double {
190 StoreObjPtr<TRGSummary> trg;
191 if (!trg)
192 return Const::doubleNaN;
193 try
194 {
195 return trg->testInput(name);
196 } catch (const std::exception&)
197 {
198 // Something went wrong, return NaN.
199 return Const::doubleNaN;
200 }
201 };
202 return func;
203 } else {
204 B2FATAL("Wrong number of arguments for L1Input function. The only argument must be the name of the input trigger bit.");
205 }
206 }
207
208 double L1InputBit(const Particle*, const std::vector<double>& arguments)
209 {
210 if (arguments.size() == 1) {
211 StoreObjPtr<TRGSummary> trg;
212 if (!trg)
213 return Const::doubleNaN;
214 try {
215 int testBit = std::lround(arguments[0]);
216 return trg->testInput(testBit);
217 } catch (const std::exception&) {
218 // Something went wrong, return NaN.
219 return Const::doubleNaN;
220 }
221 } else {
222 B2FATAL("Wrong number of arguments for L1Input function. The only argument must be the number of the input trigger bit.");
223 }
224 }
225
226 Manager::FunctionPtr L1PSNMPrescale(const std::vector<std::string>& arguments)
227 {
228 if (arguments.size() == 1) {
229 auto name = arguments[0];
230 auto func = [name](const Particle*) -> double {
231 static DBObjPtr<TRGGDLDBFTDLBits> ftdlBits;
232 if (!ftdlBits.isValid())
233 return Const::doubleNaN;
234 static DBObjPtr<TRGGDLDBPrescales> prescales;
235 if (!prescales.isValid())
236 return Const::doubleNaN;
237 for (unsigned int bit = 0; bit < TRGSummary::c_trgWordSize * TRGSummary::c_ntrgWords; bit++)
238 {
239 if (std::string(ftdlBits->getoutbitname((int)bit)) == name)
240 return prescales->getprescales(bit);
241 }
242 return Const::doubleNaN;
243 };
244 return func;
245 } else {
246 B2FATAL("Wrong number of arguments for L1Prescale function. The only argument must be the name of the PSNM trigger bit.");
247 }
248 }
249
250 double L1PSNMBitPrescale(const Particle*, const std::vector<double>& arguments)
251 {
252 if (arguments.size() == 1) {
253 int testBit = std::lround(arguments[0]);
254
255 if (testBit < 0 or testBit >= (int)TRGSummary::c_trgWordSize * (int)TRGSummary::c_ntrgWords)
256 return Const::doubleNaN;
257 static DBObjPtr<TRGGDLDBPrescales> prescales;
258 if (!prescales.isValid())
259 return Const::doubleNaN;
260 return prescales->getprescales(testBit);
261 } else {
262 B2FATAL("Wrong number of arguments for L1BitPrescale function. The only argument must be the number of the PSNM trigger bit.");
263 }
264 }
265
266 double L1TimeType(const Particle*)
267 {
268 StoreObjPtr<TRGSummary> trg;
269 if (!trg)
270 return Const::doubleNaN;
271 return trg->getTimType();
272 }
273
274 double L1TimeQuality(const Particle*)
275 {
276 StoreObjPtr<TRGSummary> trg;
277 if (!trg)
278 return Const::doubleNaN;
279 return trg->getTimQuality();
280 }
281
282 double isPoissonInInjectionVeto(const Particle*)
283 {
284 StoreObjPtr<TRGSummary> trg;
285 if (!trg)
286 return Const::doubleNaN;
287 return trg->isPoissonInInjectionVeto();
288 }
289
290 Manager::FunctionPtr softwareTriggerResult(const std::vector<std::string>& args)
291 {
292 /* The analyst has to know the name of the trigger she wants
293 * (after having looked this up from the trigger db payload)
294 *
295 * This workflow will probably improve later: but for now parse the args
296 * to check we have one name, then check the name does not throw an
297 * exception when we ask for it from the SWTR (std::map)
298 */
299 if (args.size() != 1)
300 B2FATAL("Wrong number of arguments for the function softwareTriggerResult");
301 std::string triggerIdentifier = args[0];
302
303 using namespace std::placeholders;
304 return std::bind(extractSoftwareTriggerResultImplementation, false, triggerIdentifier, _1);
305 }
306
307 Manager::FunctionPtr softwareTriggerResultNonPrescaled(const std::vector<std::string>& args)
308 {
309 /* The analyst has to know the name of the trigger she wants
310 * (after having looked this up from the trigger db payload)
311 *
312 * This workflow will probably improve later: but for now parse the args
313 * to check we have one name, then check the name does not throw an
314 * exception when we ask for it from the SWTR (std::map)
315 */
316 if (args.size() != 1)
317 B2FATAL("Wrong number of arguments for the function softwareTriggerResultNonPrescaled");
318 std::string triggerIdentifier = args[0];
319
320 using namespace std::placeholders;
321 return std::bind(extractSoftwareTriggerResultImplementation, true, triggerIdentifier, _1);
322 }
323
324 bool passesAnyHighLevelTrigger(const Particle* p)
325 {
326 // for HLT, a c_accept is a pass and all other cases are fail
327 // see mdst/dataobjects/include/SoftwareTriggerResult.h
328 std::vector<std::string> hardcodedname
329 = { "software_trigger_cut&filter&total_result" };
330 double swtcr = std::get<double>(softwareTriggerResult(hardcodedname)(p));
331 if (swtcr > 0.5) return true; // 1
332 else return false; // 0 or -1
333 }
334
335 Manager::FunctionPtr softwareTriggerPrescaling(const std::vector<std::string>& args)
336 {
337 /* The analyst has to know the name of the trigger she wants
338 * (after having looked this up from the trigger db payload)
339 *
340 * This workflow will probably improve later: but for now parse the args
341 * to check we have one name, then check the database object is valid.
342 * If not return NAN.
343 */
344 if (args.size() != 1)
345 B2FATAL("Wrong number of arguments for the function softwareTriggerPrescaling");
346 std::string triggerIdentifier = args[0];
347
348 auto outputFunction = [triggerIdentifier](const Particle*) -> double {
349
350 DBObjPtr<DBRepresentationOfSoftwareTriggerCut> downloadedCut(fullFormatIdentifier(triggerIdentifier));
351 if (not downloadedCut)
352 return Const::doubleNaN;
353 return double(downloadedCut->getPreScaleFactor());
354 };
355
356 return outputFunction;
357 }
358
359 //-------------------------------------------------------------------------
360 VARIABLE_GROUP("L1 Trigger");
361 REGISTER_VARIABLE("L1Trigger", L1Trigger,
362 "[Eventbased] Returns 1 if at least one PSNM L1 trigger bit is true.");
363 REGISTER_METAVARIABLE("L1PSNM(name)", L1PSNM,
364 R"DOC(
365[Eventbased] Returns the PSNM (Prescale And Mask, after prescale) status (1 or 0) of the output trigger bit with the given name.
366For some output trigger bits, we assign a prescale factor to reduce the number of triggered events.
367For example, we want to keep only 1% of Bhabha events. A prescale factor of 100 is then assigned to ``bha_3D`` (Bhabha selected in 3D criteria).
368Prescale factor of a given output trigger bit could be different in different datasets.
369It is recommended to use prescaled trigger bits (L1PSNM) or un-prescaled trigger bits (L1FTDL) for your analysis.
370In run-independent MC, configuration of the prescales in TSIM (trigger simulation) can be different from data, so L1 FTDL is recommended.
371In run-dependent MC, configuration of the prescales in TSIM is consistent with data, so L1PSNM is recommended.
372Please check on `the dedicated XWiki page <https://xwiki.desy.de/xwiki/rest/p/2471f>`__ or `the dedicated Belle II notes <https://docs.belle2.org/search?ln=en&p=%22Trigger+Summary%22&f=&action_search=Search&c=Belle+II+Notes>`__ to find out the definition of trigger bits.
373)DOC",
374 Manager::VariableDataType::c_double);
375 REGISTER_METAVARIABLE("L1FTDL(name)", L1FTDL,
376 R"DOC(
377[Eventbased] Returns the FTDL (Final Trigger Decision Logic, before prescale) status (1 or 0) of the output trigger bit with the given name. Output bits are the outputs of GDL, combining different input trigger bits for final decision. For example, ``ty_0/1/2/3`` is one of the input trigger bits meaning the number of neuro 3D tracks is one/two/three/more than three. While ``yyy`` is one of the output trigger bits meaning ``(ty_2 or ty_3) and !veto``. Please check on `the dedicated XWiki page <https://xwiki.desy.de/xwiki/rest/p/2471f>`__ or `the dedicated Belle II notes <https://docs.belle2.org/search?ln=en&p=%22Trigger+Summary%22&f=&action_search=Search&c=Belle+II+Notes>`__ to find out the definition of trigger bits.
378)DOC",
379 Manager::VariableDataType::c_double);
380 REGISTER_METAVARIABLE("L1Input(name)", L1Input,
381 R"DOC(
382[Eventbased] Returns the input bit status (1 or 0) of the trigger bit with the given name. Input trigger bits are predefined selections from each sub-detector, with adjustment of the delay and width, in order to fix latency on GDL. For example, ``ty_0/1/2/3`` is one of the input trigger bits meaning the number of neuro 3D tracks is one/two/three/more than three. Please check on `the dedicated XWiki page <https://xwiki.desy.de/xwiki/rest/p/2471f>`__ or `the dedicated Belle II notes <https://docs.belle2.org/search?ln=en&p=%22Trigger+Summary%22&f=&action_search=Search&c=Belle+II+Notes>`__ to find out the definition of trigger bits.
383)DOC",
384 Manager::VariableDataType::c_double);
385 REGISTER_METAVARIABLE("L1Prescale(name)", L1PSNMPrescale,
386 R"DOC(
387[Eventbased] Returns the PSNM (prescale and mask) prescale factor of the trigger bit with the given name. Definition of prescale factor is shown in a few lines before in `L1PSNM`. Prescale factors are usually dependent on different datasets.
388)DOC",
389 Manager::VariableDataType::c_double);
390 REGISTER_VARIABLE("L1PSNMBit(i)", L1PSNMBit,
391 R"DOC(
392[Eventbased] Returns the PSNM (Prescale And Mask, after prescale) status (1 or 0) of i-th trigger bit.
393
394.. warning::
395 It is recommended to use this variable only for debugging and to use :b2:var:`L1PSNM`
396 with the explicit trigger bit name for physics analyses or performance studies.
397)DOC");
398 REGISTER_VARIABLE("L1FTDLBit(i)", L1FTDLBit,
399 R"DOC(
400[Eventbased] Returns the FTDL (Final Trigger Decision Logic, before prescale) status (1 or 0) of i-th trigger bit.
401
402.. warning::
403 It is recommended to use this variable only for debugging and to use :b2:var:`L1FTDL`
404 with the explicit trigger bit name for physics analyses or performance studies.
405)DOC");
406 REGISTER_VARIABLE("L1InputBit(i)", L1InputBit,
407 R"DOC(
408[Eventbased] Returns the input bit status (1 or 0) of the i-th input trigger bit.
409
410.. warning::
411 It is recommended to use this variable only for debugging and to use :b2:var:`L1Input`
412 with the explicit trigger bit name for physics analyses or performance studies.
413)DOC");
414 REGISTER_VARIABLE("L1PSNMBitPrescale(i)", L1PSNMBitPrescale,
415 R"DOC(
416[Eventbased] Returns the PSNM (prescale and mask) prescale of i-th trigger bit.
417
418.. warning::
419 It is recommended to use this variable only for debugging and to use :b2:var:`L1Prescale`
420 with the explicit trigger bit name for physics analyses or performance studies.
421)DOC");
422 REGISTER_VARIABLE("L1TimeType", L1TimeType,
423 "[Eventbased] Returns kind of detector which determines the Level1 trigger timing. 0:ECL, 1:TOP, 2:SELF(timing of PSNM bit), 3:CDC, 5:delayed bhabha, 7: random, 13:poisson.");
424 REGISTER_VARIABLE("L1TimeQuality", L1TimeQuality,
425 "[Eventbased] Returns expected Level1 timing resolution. This flag will be used for SVD 3-point sampling in future. 0:None; 1:Coarse (sigma > x ns); 2:FINE (sigma < x ns); x has been set to about 5ns before LS1 but can be changed in future");
426 REGISTER_VARIABLE("isPoissonTriggerInInjectionVeto", isPoissonInInjectionVeto,
427 "[Eventbased] Returns 1 if the poisson random trigger is within the injection veto window.");
428 //-------------------------------------------------------------------------
429 VARIABLE_GROUP("Software Trigger");
430 REGISTER_METAVARIABLE("SoftwareTriggerResult(triggerIdentifier)", softwareTriggerResult, R"DOC(
431[Eventbased] [Expert] returns the SoftwareTriggerCutResult, defined as reject (-1), accept (1), or noResult (0).
432If the trigger identifier is not found, returns NaN.
433
434For example:
435
436.. code-block::
437
438 SoftwareTriggerResult(filter 1_Estargt1_GeV_cluster_no_other_cluster_Estargt0.3_GeV)
439
440which is equivalent to
441
442.. code-block::
443
444 SoftwareTriggerResult(software_trigger_cut&filter&1_Estargt1_GeV_cluster_no_other_cluster_Estargt0.3_GeV)
445
446
447.. warning:: the meanings of these change depending if using trigger or the skim stage, hence expert.
448
449.. seealso:: ``b2hlt_triggers`` for possible triggerIdentifiers.
450
451 )DOC", Manager::VariableDataType::c_double);
452
453 REGISTER_METAVARIABLE("SoftwareTriggerResultNonPrescaled(triggerIdentifier)", softwareTriggerResultNonPrescaled,
454 "[Eventbased] [Expert] returns the SoftwareTriggerCutResult, "
455 "if this trigger would not be prescaled."
456 "Please note, this is not the final HLT decision! "
457 "It is defined as reject (-1), accept (1), or noResult (0). Note "
458 "that the meanings of these change depending if using trigger "
459 "or the skim stage, hence expert."
460 "If the trigger identifier is not found, returns NaN.", Manager::VariableDataType::c_double);
461 REGISTER_VARIABLE("HighLevelTrigger", passesAnyHighLevelTrigger,
462 "[Eventbased] True if event passes the HLT trigger, false if not");
463 REGISTER_METAVARIABLE("SoftwareTriggerPrescaling(triggerIdentifier)", softwareTriggerPrescaling,
464 "[Eventbased] return the prescaling for the specific software trigger identifier. "
465 "Please note, this prescaling is taken from the currently setup database. It only corresponds "
466 "to the correct HLT prescale if you are using the online database!"
467 "If the trigger identifier is not found, returns NaN.", Manager::VariableDataType::c_double);
468 //-------------------------------------------------------------------------
469 }
471}
static const double doubleNaN
quiet_NaN
Definition Const.h:704
Class to store reconstructed particles.
Definition Particle.h:76
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
static const unsigned int c_trgWordSize
size of a l1 trigger word
Definition TRGSummary.h:37
static const unsigned int c_ntrgWords
number of l1 trigger words
Definition TRGSummary.h:40
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
Definition Manager.h:112
SoftwareTriggerCutResult
Enumeration with all possible results of the SoftwareTriggerCut.
Abstract base class for different kinds of events.