Belle II Software  release-05-01-25
decaydescriptor.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2018 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Sam Cunliffe *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <analysis/DecayDescriptor/DecayDescriptor.h>
12 #include <analysis/dataobjects/Particle.h>
13 
14 #include <framework/datastore/StoreArray.h>
15 #include <framework/utilities/TestHelpers.h>
16 
17 #include <gtest/gtest.h>
18 #include <string>
19 #include <vector>
20 
21 using namespace Belle2;
22 
23 namespace {
24  TEST(DecayDescriptorTest, TrivialUse)
25  {
26  // trivial decay descriptor == particle name
27  DecayDescriptor dd;
28  bool initok = dd.init("K+");
29  EXPECT_EQ(initok, true);
30  ASSERT_NE(dd.getMother(), nullptr);
31  EXPECT_EQ(dd.getMother()->getName(), "K+");
32  EXPECT_EQ(dd.getMother()->getLabel(), "");
33  EXPECT_EQ(dd.getMother()->getFullName(), "K+");
34  EXPECT_EQ(dd.getMother()->getPDGCode(), 321);
35  EXPECT_EQ(dd.getNDaughters(), 0);
36  }
37 
38  TEST(DecayDescriptorTest, NormalBehaviour)
39  {
40  DecayDescriptor dd;
41  bool initok = dd.init("B0:cand -> K+:loose pi-:loose");
42 
43  EXPECT_EQ(initok, true);
44 
45  // standard arrow, not an inclusive decay
46  EXPECT_EQ(dd.isIgnoreRadiatedPhotons(), true);
47  EXPECT_EQ(dd.isIgnoreIntermediate(), true);
48 
49  ASSERT_NE(dd.getMother(), nullptr);
50  EXPECT_EQ(dd.getMother()->getName(), "B0");
51  EXPECT_EQ(dd.getMother()->getLabel(), "cand");
52  EXPECT_EQ(dd.getMother()->getPDGCode(), 511);
53  EXPECT_EQ(dd.getMother()->getFullName(), "B0:cand");
54  EXPECT_EQ(dd.getNDaughters(), 2);
55 
56  EXPECT_EQ(dd.getDaughter(0)->getNDaughters(), 0);
57  EXPECT_EQ(dd.getDaughter(0)->getMother()->getName(), "K+");
58  EXPECT_EQ(dd.getDaughter(0)->getMother()->getLabel(), "loose");
59  EXPECT_EQ(dd.getDaughter(0)->getMother()->getPDGCode(), 321);
60  EXPECT_EQ(dd.getDaughter(0)->getMother()->getFullName(), "K+:loose");
61 
62  EXPECT_EQ(dd.getDaughter(1)->getNDaughters(), 0);
63  EXPECT_EQ(dd.getDaughter(1)->getMother()->getName(), "pi-");
64  EXPECT_EQ(dd.getDaughter(1)->getMother()->getLabel(), "loose");
65  EXPECT_EQ(dd.getDaughter(1)->getMother()->getPDGCode(), -211);
66  EXPECT_EQ(dd.getDaughter(1)->getMother()->getFullName(), "pi-:loose");
67 
68  ASSERT_EQ(dd.getDaughter(2), nullptr);
69  }
70 
71  TEST(DecayDescriptorTest, Granddaughters)
72  {
73  DecayDescriptor dd;
74  bool initok = dd.init(
75  "B0:cand -> [D0:dau1 -> K+:grandau pi-:grandau] [pi0:dau2 -> gamma:grandau [gamma:converted -> e+:gtgrandau e-:gtgrandau]]"
76  );
77  EXPECT_EQ(initok, true);
78  ASSERT_NE(dd.getMother(), nullptr);
79  EXPECT_EQ(dd.getNDaughters(), 2);
80 
81  // D0 -> K pi
82  EXPECT_EQ(dd.getDaughter(0)->getMother()->getName(), "D0");
83  EXPECT_EQ(dd.getDaughter(0)->getMother()->getPDGCode(), 421);
84  EXPECT_EQ(dd.getDaughter(0)->getNDaughters(), 2);
85  EXPECT_EQ(dd.getDaughter(0)->getDaughter(0)->getMother()->getName(), "K+");
86  EXPECT_EQ(dd.getDaughter(0)->getDaughter(0)->getNDaughters(), 0);
87  EXPECT_EQ(dd.getDaughter(0)->getDaughter(1)->getMother()->getName(), "pi-");
88  EXPECT_EQ(dd.getDaughter(0)->getDaughter(1)->getNDaughters(), 0);
89  ASSERT_EQ(dd.getDaughter(0)->getDaughter(2), nullptr);
90 
91  // pi0 -> gamma gamma; gamma -> ee
92  EXPECT_EQ(dd.getDaughter(1)->getMother()->getName(), "pi0");
93  EXPECT_EQ(dd.getDaughter(1)->getMother()->getPDGCode(), 111);
94  EXPECT_EQ(dd.getDaughter(1)->getNDaughters(), 2);
95  EXPECT_EQ(dd.getDaughter(1)->getDaughter(0)->getMother()->getName(), "gamma");
96  EXPECT_EQ(dd.getDaughter(1)->getDaughter(0)->getMother()->getLabel(), "grandau");
97  EXPECT_EQ(dd.getDaughter(1)->getDaughter(0)->getMother()->getPDGCode(), 22);
98  EXPECT_EQ(dd.getDaughter(1)->getDaughter(0)->getNDaughters(), 0);
99  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getMother()->getName(), "gamma");
100  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getMother()->getLabel(), "converted");
101  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getMother()->getPDGCode(), 22);
102  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getNDaughters(), 2);
103  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getDaughter(0)->getMother()->getName(), "e+");
104  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getDaughter(0)->getMother()->getPDGCode(), -11);
105  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getDaughter(1)->getMother()->getName(), "e-");
106  EXPECT_EQ(dd.getDaughter(1)->getDaughter(1)->getDaughter(1)->getMother()->getPDGCode(), 11);
107  ASSERT_EQ(dd.getDaughter(1)->getDaughter(1)->getDaughter(2), nullptr);
108  ASSERT_EQ(dd.getDaughter(1)->getDaughter(2), nullptr);
109 
110  ASSERT_EQ(dd.getDaughter(2), nullptr);
111  }
112 
113  TEST(DecayDescriptorTest, ArrowsDecaysGrammar)
114  {
115  // =direct=> means ignore intermediate resonances
116  DecayDescriptor dd1;
117  bool initok = dd1.init("B0:candidates =direct=> K+:loose pi-:loose gamma:clean");
118  EXPECT_EQ(initok, true);
119  EXPECT_EQ(dd1.isIgnoreRadiatedPhotons(), true);
120  EXPECT_EQ(dd1.isIgnoreIntermediate(), false);
121 
122  // =norad=> means ignore photons
123  DecayDescriptor dd2;
124  initok = dd2.init("B0:candidates =norad=> K+:loose pi-:loose gamma:clean");
125  EXPECT_EQ(initok, true);
126  EXPECT_EQ(dd2.isIgnoreRadiatedPhotons(), false);
127  EXPECT_EQ(dd2.isIgnoreIntermediate(), true);
128 
129  // =exact=> means ignore intermediate resonances *and* photons
130  DecayDescriptor dd3;
131  initok = dd3.init("B0:candidates =exact=> K+:loose pi-:loose gamma:clean");
132  EXPECT_EQ(initok, true);
133  EXPECT_EQ(dd3.isIgnoreRadiatedPhotons(), false);
134  EXPECT_EQ(dd3.isIgnoreIntermediate(), false);
135 
136  }
137 
138  TEST(DecayDescriptorTest, KeywordDecaysGrammar)
139  {
140  // ... means accept missing massive
141  DecayDescriptor dd1;
142  bool initok = dd1.init("B0:candidates -> K+:loose gamma:clean ...");
143  EXPECT_EQ(initok, true);
144  EXPECT_EQ(dd1.isIgnoreRadiatedPhotons(), true);
145  EXPECT_EQ(dd1.isIgnoreIntermediate(), true);
146  EXPECT_EQ(dd1.isIgnoreMassive(), true);
147  EXPECT_EQ(dd1.isIgnoreNeutrino(), false);
148  EXPECT_EQ(dd1.isIgnoreGamma(), false);
149  EXPECT_EQ(dd1.isIgnoreBrems(), false);
150 
151  // ?nu means accept missing neutrino
152  DecayDescriptor dd2;
153  initok = dd2.init("B0:candidates -> K+:loose pi-:loose ?nu");
154  EXPECT_EQ(initok, true);
155  EXPECT_EQ(dd2.isIgnoreRadiatedPhotons(), true);
156  EXPECT_EQ(dd2.isIgnoreIntermediate(), true);
157  EXPECT_EQ(dd2.isIgnoreMassive(), false);
158  EXPECT_EQ(dd2.isIgnoreNeutrino(), true);
159  EXPECT_EQ(dd2.isIgnoreGamma(), false);
160  EXPECT_EQ(dd2.isIgnoreBrems(), false);
161 
162  // !nu does not change anything. It is reserved for future updates.
163  DecayDescriptor dd3;
164  initok = dd3.init("B0:candidates -> K+:loose pi-:loose !nu");
165  EXPECT_EQ(initok, true);
166  EXPECT_EQ(dd3.isIgnoreRadiatedPhotons(), true);
167  EXPECT_EQ(dd3.isIgnoreIntermediate(), true);
168  EXPECT_EQ(dd3.isIgnoreMassive(), false);
169  EXPECT_EQ(dd3.isIgnoreNeutrino(), false);
170  EXPECT_EQ(dd3.isIgnoreGamma(), false);
171  EXPECT_EQ(dd3.isIgnoreBrems(), false);
172 
173  // ?gamma means ignore missing gamma
174  DecayDescriptor dd4;
175  initok = dd4.init("B0:candidates -> K+:loose pi-:loose ?gamma");
176  EXPECT_EQ(initok, true);
177  EXPECT_EQ(dd4.isIgnoreRadiatedPhotons(), true);
178  EXPECT_EQ(dd4.isIgnoreIntermediate(), true);
179  EXPECT_EQ(dd4.isIgnoreMassive(), false);
180  EXPECT_EQ(dd4.isIgnoreNeutrino(), false);
181  EXPECT_EQ(dd4.isIgnoreGamma(), true);
182  EXPECT_EQ(dd4.isIgnoreBrems(), false);
183 
184  // !gamma does not change anything. It is reserved for future updates.
185  DecayDescriptor dd5;
186  initok = dd5.init("B0:candidates -> K+:loose pi-:loose !gamma");
187  EXPECT_EQ(initok, true);
188  EXPECT_EQ(dd5.isIgnoreRadiatedPhotons(), true);
189  EXPECT_EQ(dd5.isIgnoreIntermediate(), true);
190  EXPECT_EQ(dd5.isIgnoreMassive(), false);
191  EXPECT_EQ(dd5.isIgnoreNeutrino(), false);
192  EXPECT_EQ(dd5.isIgnoreGamma(), false);
193  EXPECT_EQ(dd5.isIgnoreBrems(), false);
194 
195  // ... ?nu ?gamma means accept missing massive
196  DecayDescriptor dd6;
197  initok = dd6.init("B0:candidates -> e-:loose ... ?nu ?gamma");
198  EXPECT_EQ(initok, true);
199  EXPECT_EQ(dd6.isIgnoreRadiatedPhotons(), true);
200  EXPECT_EQ(dd6.isIgnoreIntermediate(), true);
201  EXPECT_EQ(dd6.isIgnoreMassive(), true);
202  EXPECT_EQ(dd6.isIgnoreNeutrino(), true);
203  EXPECT_EQ(dd6.isIgnoreGamma(), true);
204  EXPECT_EQ(dd6.isIgnoreBrems(), false);
205 
206  // ?addbrems means ignore photon added by Brems-correction tools (modularAnalysis.correctBrems / modularAnalysis.correctBremsBelle)
207  DecayDescriptor dd7;
208  initok = dd7.init("B0:candidates -> K+:loose pi-:loose ?addbrems");
209  EXPECT_EQ(initok, true);
210  EXPECT_EQ(dd7.isIgnoreRadiatedPhotons(), true);
211  EXPECT_EQ(dd7.isIgnoreIntermediate(), true);
212  EXPECT_EQ(dd7.isIgnoreMassive(), false);
213  EXPECT_EQ(dd7.isIgnoreNeutrino(), false);
214  EXPECT_EQ(dd7.isIgnoreGamma(), false);
215  EXPECT_EQ(dd7.isIgnoreBrems(), true);
216 
217  }
218 
219  TEST(DecayDescriptorTest, UnspecifiedParticleGrammar)
220  {
221  // @ means unspecified particle, for example @Xsd -> K+ pi-
222  DecayDescriptor dd1;
223  bool initok = dd1.init("@Xsd:candidates -> K+:loose pi-:loose");
224  EXPECT_EQ(initok, true);
225  ASSERT_NE(dd1.getMother(), nullptr);
226  EXPECT_EQ(dd1.getMother()->getName(), "Xsd");
227  EXPECT_EQ(dd1.getMother()->isUnspecified(), true);
228  EXPECT_EQ(dd1.getMother()->isSelected(), false);
229 
230  // Both selectors, @ and ^, can be used at the same time
231  DecayDescriptor dd2;
232  initok = dd2.init("^@Xsd:candidates -> K+:loose pi-:loose");
233  EXPECT_EQ(initok, true);
234  EXPECT_EQ(dd2.getMother()->getName(), "Xsd");
235  EXPECT_EQ(dd2.getMother()->isUnspecified(), true);
236  EXPECT_EQ(dd2.getMother()->isSelected(), true);
237 
238  DecayDescriptor dd3;
239  initok = dd3.init("@^Xsd:candidates -> K+:loose pi-:loose");
240  EXPECT_EQ(initok, true);
241  EXPECT_EQ(dd3.getMother()->getName(), "Xsd");
242  EXPECT_EQ(dd3.getMother()->isUnspecified(), true);
243  EXPECT_EQ(dd3.getMother()->isSelected(), true);
244 
245 
246  // @ can be attached to a daughter
247  DecayDescriptor dd4;
248  initok = dd4.init("B0:Xsdee -> @Xsd e+:loose e-:loose");
249  EXPECT_EQ(initok, true);
250 
251  ASSERT_NE(dd4.getMother(), nullptr);
252  EXPECT_EQ(dd4.getMother()->isUnspecified(), false);
253  EXPECT_EQ(dd4.getMother()->isSelected(), false);
254 
255  EXPECT_EQ(dd4.getDaughter(0)->getMother()->getName(), "Xsd");
256  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isUnspecified(), true);
257  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isSelected(), false);
258 
259  // Both selectors, @ and ^, can be used at the same time
260  DecayDescriptor dd5;
261  initok = dd5.init("B0:Xsdee -> ^@Xsd e+:loose e-:loose");
262  EXPECT_EQ(initok, true);
263  EXPECT_EQ(dd5.getDaughter(0)->getMother()->getName(), "Xsd");
264  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isUnspecified(), true);
265  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isSelected(), true);
266 
267  DecayDescriptor dd6;
268  initok = dd6.init("B0:Xsdee -> @^Xsd e+:loose e-:loose");
269  EXPECT_EQ(initok, true);
270  EXPECT_EQ(dd6.getDaughter(0)->getMother()->getName(), "Xsd");
271  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isUnspecified(), true);
272  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isSelected(), true);
273 
274  }
275 
276  TEST(DecayDescriptorTest, GrammarWithNestedDecay)
277  {
278  // ... means accept missing massive
279  DecayDescriptor dd1;
280  bool initok = dd1.init("B0:candidates =direct=> [D-:pi =norad=> pi-:loose ... ?gamma] e+:loose ?nu ?addbrems");
281  EXPECT_EQ(initok, true);
282 
283  EXPECT_EQ(dd1.isIgnoreRadiatedPhotons(), true);
284  EXPECT_EQ(dd1.isIgnoreIntermediate(), false);
285  EXPECT_EQ(dd1.isIgnoreMassive(), false);
286  EXPECT_EQ(dd1.isIgnoreNeutrino(), true);
287  EXPECT_EQ(dd1.isIgnoreGamma(), false);
288  EXPECT_EQ(dd1.isIgnoreBrems(), true);
289 
290  const DecayDescriptor* dd1_D = dd1.getDaughter(0);
291  EXPECT_EQ(dd1_D->getMother()->getName(), "D-");
292  EXPECT_EQ(dd1_D->isIgnoreRadiatedPhotons(), false);
293  EXPECT_EQ(dd1_D->isIgnoreIntermediate(), true);
294  EXPECT_EQ(dd1_D->isIgnoreMassive(), true);
295  EXPECT_EQ(dd1_D->isIgnoreNeutrino(), false);
296  EXPECT_EQ(dd1_D->isIgnoreGamma(), true);
297  EXPECT_EQ(dd1_D->isIgnoreBrems(), false);
298 
299  }
300 
301 
302  TEST(DecayDescriptorTest, SelectionParticles)
303  {
304  DecayDescriptor dd1;
305  bool initok = dd1.init("B0:B2Dzpipi -> [D0 -> ^K+:loose pi-:loose] pi+:loose pi-:loose");
306  EXPECT_EQ(initok, true);
307  std::vector<std::string> names = dd1.getSelectionNames();
308  ASSERT_EQ(names.size(), 1);
309  EXPECT_EQ(names[0], "B0_D0_K");
310 
311  // add another selection particle to an already existing decay descriptor
312  // not sure exactly who is using this feature, but might as well test it.
313  initok = dd1.init("B0:B2Dzpipi -> [D0 -> K+:loose ^pi-:loose] pi+:loose pi-:loose");
314  EXPECT_EQ(initok, true);
315  names = dd1.getSelectionNames();
316  ASSERT_EQ(names.size(), 2);
317  EXPECT_EQ(names[0], "B0_D0_K");
318  EXPECT_EQ(names[1], "B0_D0_pi");
319 
320  // more complex decay string with multiple particles of the same type
321  DecayDescriptor dd2;
322  initok = dd2.init("vpho:complex -> [D0 -> ^K+:loose pi-:loose] ^e+:loose ^e-:loose ^gamma:loose");
323  EXPECT_EQ(initok, true);
324  names = dd2.getSelectionNames();
325  ASSERT_EQ(names.size(), 4);
326  EXPECT_EQ(names[0], "vpho_D0_K");
327  EXPECT_EQ(names[1], "vpho_e0");
328  EXPECT_EQ(names[2], "vpho_e1");
329  EXPECT_EQ(names[3], "vpho_gamma");
330  }
331 
332  TEST(DecayDescriptorTest, MisIDandDecayInFlightGrammar)
333  {
334  // MisID is ignored for a daughter which has (misID) in the head
335  DecayDescriptor dd1;
336  bool initok = dd1.init("B0:sig -> (misID)K+:loose pi-:loose");
337  EXPECT_EQ(initok, true);
338  ASSERT_NE(dd1.getMother(), nullptr);
339  EXPECT_EQ(dd1.getMother()->getName(), "B0");
340  EXPECT_EQ(dd1.getMother()->isIgnoreMisID(), false);
341  EXPECT_EQ(dd1.getMother()->isIgnoreDecayInFlight(), false);
342  ASSERT_NE(dd1.getDaughter(0), nullptr);
343  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getName(), "K+");
344  EXPECT_EQ(dd1.getDaughter(0)->getMother()->isIgnoreMisID(), true);
345  EXPECT_EQ(dd1.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
346  ASSERT_NE(dd1.getDaughter(1), nullptr);
347  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getName(), "pi-");
348  EXPECT_EQ(dd1.getDaughter(1)->getMother()->isIgnoreMisID(), false);//
349  EXPECT_EQ(dd1.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
350 
351  DecayDescriptor dd2;
352  initok = dd2.init("B0:sig -> K+:loose (misID)pi-:loose");
353  EXPECT_EQ(initok, true);
354  ASSERT_NE(dd2.getDaughter(0), nullptr);
355  EXPECT_EQ(dd2.getDaughter(0)->getMother()->getName(), "K+");
356  EXPECT_EQ(dd2.getDaughter(0)->getMother()->isIgnoreMisID(), false);//
357  EXPECT_EQ(dd2.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
358  ASSERT_NE(dd2.getDaughter(1), nullptr);
359  EXPECT_EQ(dd2.getDaughter(1)->getMother()->getName(), "pi-");
360  EXPECT_EQ(dd2.getDaughter(1)->getMother()->isIgnoreMisID(), true);
361  EXPECT_EQ(dd2.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
362 
363  DecayDescriptor dd3;
364  initok = dd3.init("B0:sig -> (misID)K+:loose (misID)pi-:loose");
365  EXPECT_EQ(initok, true);
366  ASSERT_NE(dd3.getDaughter(0), nullptr);
367  EXPECT_EQ(dd3.getDaughter(0)->getMother()->getName(), "K+");
368  EXPECT_EQ(dd3.getDaughter(0)->getMother()->isIgnoreMisID(), true);
369  EXPECT_EQ(dd3.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
370  ASSERT_NE(dd3.getDaughter(1), nullptr);
371  EXPECT_EQ(dd3.getDaughter(1)->getMother()->getName(), "pi-");
372  EXPECT_EQ(dd3.getDaughter(1)->getMother()->isIgnoreMisID(), true);
373  EXPECT_EQ(dd3.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
374 
375  // DecayInFlight is ignored for a daughter which has (decay) in the head
376  DecayDescriptor dd4;
377  initok = dd4.init("B0:sig -> (decay)K+:loose pi-:loose");
378  EXPECT_EQ(initok, true);
379  ASSERT_NE(dd4.getDaughter(0), nullptr);
380  EXPECT_EQ(dd4.getDaughter(0)->getMother()->getName(), "K+");
381  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isIgnoreMisID(), false);
382  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
383  ASSERT_NE(dd4.getDaughter(1), nullptr);
384  EXPECT_EQ(dd4.getDaughter(1)->getMother()->getName(), "pi-");
385  EXPECT_EQ(dd4.getDaughter(1)->getMother()->isIgnoreMisID(), false);
386  EXPECT_EQ(dd4.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);//
387 
388  DecayDescriptor dd5;
389  initok = dd5.init("B0:sig -> K+:loose (decay)pi-:loose");
390  EXPECT_EQ(initok, true);
391  ASSERT_NE(dd5.getDaughter(0), nullptr);
392  EXPECT_EQ(dd5.getDaughter(0)->getMother()->getName(), "K+");
393  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isIgnoreMisID(), false);
394  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);//
395  ASSERT_NE(dd5.getDaughter(1), nullptr);
396  EXPECT_EQ(dd5.getDaughter(1)->getMother()->getName(), "pi-");
397  EXPECT_EQ(dd5.getDaughter(1)->getMother()->isIgnoreMisID(), false);
398  EXPECT_EQ(dd5.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
399 
400  DecayDescriptor dd6;
401  initok = dd6.init("B0:sig -> (decay)K+:loose (decay)pi-:loose");
402  EXPECT_EQ(initok, true);
403  ASSERT_NE(dd6.getDaughter(0), nullptr);
404  EXPECT_EQ(dd6.getDaughter(0)->getMother()->getName(), "K+");
405  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isIgnoreMisID(), false);
406  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
407  ASSERT_NE(dd6.getDaughter(1), nullptr);
408  EXPECT_EQ(dd6.getDaughter(1)->getMother()->getName(), "pi-");
409  EXPECT_EQ(dd6.getDaughter(1)->getMother()->isIgnoreMisID(), false);
410  EXPECT_EQ(dd6.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
411 
412  // @, ^, (misID), and (decay) can be used at the same time
413  DecayDescriptor dd7;
414  initok = dd7.init("B0:sig -> (misID)(decay)K+:loose (decay)(misID)pi-:loose");
415  EXPECT_EQ(initok, true);
416  ASSERT_NE(dd7.getDaughter(0), nullptr);
417  EXPECT_EQ(dd7.getDaughter(0)->getMother()->getName(), "K+");
418  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isSelected(), false);
419  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isUnspecified(), false);
420  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isIgnoreMisID(), true);
421  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
422  ASSERT_NE(dd7.getDaughter(1), nullptr);
423  EXPECT_EQ(dd7.getDaughter(1)->getMother()->getName(), "pi-");
424  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isSelected(), false);
425  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isUnspecified(), false);
426  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isIgnoreMisID(), true);
427  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
428 
429  DecayDescriptor dd8;
430  initok = dd8.init("B0:sig -> ^(misID)K+:loose (decay)@pi-:loose");
431  EXPECT_EQ(initok, true);
432  ASSERT_NE(dd8.getDaughter(0), nullptr);
433  EXPECT_EQ(dd8.getDaughter(0)->getMother()->getName(), "K+");
434  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isSelected(), true);
435  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isUnspecified(), false);
436  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isIgnoreMisID(), true);
437  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
438  ASSERT_NE(dd8.getDaughter(1), nullptr);
439  EXPECT_EQ(dd8.getDaughter(1)->getMother()->getName(), "pi-");
440  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isSelected(), false);
441  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isUnspecified(), true);
442  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isIgnoreMisID(), false);
443  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
444 
445  DecayDescriptor dd9;
446  initok = dd9.init("B0:sig -> ^@(misID)(decay)K+:loose (decay)@^(misID)pi-:loose");
447  EXPECT_EQ(initok, true);
448  ASSERT_NE(dd9.getDaughter(0), nullptr);
449  EXPECT_EQ(dd9.getDaughter(0)->getMother()->getName(), "K+");
450  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isSelected(), true);
451  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isUnspecified(), true);
452  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isIgnoreMisID(), true);
453  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
454  ASSERT_NE(dd9.getDaughter(1), nullptr);
455  EXPECT_EQ(dd9.getDaughter(1)->getMother()->getName(), "pi-");
456  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isSelected(), true);
457  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isUnspecified(), true);
458  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isIgnoreMisID(), true);
459  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
460 
461  }
462 
463  TEST(DecayDescriptorTest, BadLabelTest)
464  {
465  // use of illegal characters in labels
466  DecayDescriptor dd1;
467  bool initok = dd1.init("B0:lab[el -> K+:loose pi-:loose");
468  EXPECT_EQ(initok, false);
469  EXPECT_EQ(dd1.getMother()->getName(), "");
470  EXPECT_EQ(dd1.getMother()->getLabel(), "");
471 
472  DecayDescriptor dd2;
473  initok = dd2.init("B0:lab^el -> K+:loose pi-:loose");
474  EXPECT_EQ(initok, false);
475  EXPECT_EQ(dd2.getMother()->getName(), "");
476  EXPECT_EQ(dd2.getMother()->getLabel(), "");
477 
478  DecayDescriptor dd3;
479  initok = dd3.init("B0:lab]el -> K+:loose pi-:loose");
480  EXPECT_EQ(initok, false);
481  EXPECT_EQ(dd3.getMother()->getName(), "");
482  EXPECT_EQ(dd3.getMother()->getLabel(), "");
483 
484  DecayDescriptor dd4;
485  initok = dd4.init("B0:lab>el -> K+:loose pi-:loose");
486  EXPECT_EQ(initok, false);
487  EXPECT_EQ(dd4.getMother()->getName(), "");
488  EXPECT_EQ(dd4.getMother()->getLabel(), "");
489 
490  DecayDescriptor dd5;
491  initok = dd5.init("B0:lab:el -> K+:loose pi-:loose");
492  EXPECT_EQ(initok, false);
493  EXPECT_EQ(dd5.getMother()->getName(), "");
494  EXPECT_EQ(dd5.getMother()->getLabel(), "");
495  }
496 
497  TEST(DecayDescriptorTest, UnicodeTest)
498  {
499  // this is broken with boost 1.72, still need to investigate
500  return;
501  // use of unicode characters in labels
502  const std::string weird = "⨔π⁰=πŸ–ΌπŸ”°";
503  DecayDescriptor dd1;
504  bool initok = dd1.init("B0:" + weird + " -> K+:πŸ’©πŸ˜œ pi-:πŸ’―πŸ†πŸ’¦");
505  ASSERT_EQ(initok, true);
506  EXPECT_EQ(dd1.getMother()->getName(), "B0");
507  EXPECT_EQ(dd1.getMother()->getLabel(), weird);
508  ASSERT_EQ(dd1.getNDaughters(), 2);
509  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getName(), "K+");
510  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getName(), "pi-");
511  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getLabel(), "πŸ’©πŸ˜œ");
512  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getLabel(), "πŸ’―πŸ†πŸ’¦");
513  }
514 
515  TEST(DecayDescriptorTest, BadGrammarTest)
516  {
517  DecayDescriptor dd1;
518  bool initok = dd1.init("B0:label ---> K+:loose pi-:loose");
519  EXPECT_EQ(initok, false);
520 
521  DecayDescriptor dd2;
522  initok = dd2.init("B0:label > K+:loose pi-:loose");
523  EXPECT_EQ(initok, false);
524 
525  DecayDescriptor dd3;
526  initok = dd3.init("B0:label -> K+::loose pi-:loose");
527  EXPECT_EQ(initok, false);
528 
529  DecayDescriptor dd4;
530  initok = dd4.init("B0:label K+:loose pi-:loose");
531  EXPECT_EQ(initok, false);
532 
533  DecayDescriptor dd5;
534  initok = dd5.init("B0:label <- K+:loose pi-:loose");
535  EXPECT_EQ(initok, false);
536 
537  DecayDescriptor dd6;
538  initok = dd6.init("B0:label => K+:loose pi-:loose");
539  EXPECT_EQ(initok, false);
540 
541  DecayDescriptor dd7;
542  initok = dd7.init("B0:label --> K+:loose pi-:loose");
543  EXPECT_EQ(initok, false);
544 
545  DecayDescriptor dd8;
546  initok = dd8.init("B0:label ==> K+:loose pi-:loose");
547  EXPECT_EQ(initok, false);
548  }
549 
550  TEST(DecayDescriptorTest, B2ParticleInterface)
551  {
552  // need datastore for the particles StoreArray
554  StoreArray<Particle> particles;
555  particles.registerInDataStore();
557 
558  // mock up a composite Belle2::Particle
559  TLorentzVector zeroes(0, 0, 0, 0);
560  Particle* Kp = particles.appendNew(Particle(zeroes, 321)); // 0
561  Particle* pim1 = particles.appendNew(Particle(zeroes, -211)); // 1
562  Particle* pim2 = particles.appendNew(Particle(zeroes, -211)); // 2
563  Particle* pip = particles.appendNew(Particle(zeroes, 211)); // 3
564  Particle* D0 = particles.appendNew(Particle(zeroes, 421)); // 4
565  D0->appendDaughter(0);
566  D0->appendDaughter(1);
567  Particle* B0 = particles.appendNew(Particle(zeroes, 511)); // 5
568  B0->appendDaughter(4);
569  B0->appendDaughter(3);
570  B0->appendDaughter(2);
571 
572  // ---
573  DecayDescriptor dd;
574  bool initok = dd.init("B0:B2Dzpipi -> [D0 -> K+:loose ^pi-:loose] ^pi+:loose pi-:loose");
575  ASSERT_EQ(initok, true);
576 
577  std::vector<const Particle*> selectionparticles = dd.getSelectionParticles(B0);
578  EXPECT_EQ(selectionparticles.size(), 2);
579  EXPECT_EQ(selectionparticles[0], pim1);
580  EXPECT_EQ(selectionparticles[1], pip);
581 
582  EXPECT_B2ERROR(dd.getSelectionParticles(D0));
583 
584  EXPECT_B2WARNING(dd.getSelectionParticles(pip));
585  EXPECT_B2WARNING(dd.getSelectionParticles(Kp));
586  EXPECT_B2WARNING(dd.getSelectionParticles(pim1));
587  EXPECT_B2WARNING(dd.getSelectionParticles(pim2));
588 
589  EXPECT_EQ(dd.getSelectionParticles(D0).size(), 0);
590 
592  }
593 
594  TEST(DecayDescriptorTest, HierarchyDefinitionTest)
595  {
596  DecayDescriptor dd;
597  bool initok = dd.init("B+ -> [ D+ -> ^K+ pi0 ] ^pi0");
598  EXPECT_EQ(initok, true);
599 
600  auto selected_hierarchies = dd.getHierarchyOfSelected();
601 
602  std::vector<std::vector<std::pair<int, std::string>>> expected_hierarchies;
603  std::vector<std::pair<int, std::string>> K_path;
604  std::vector<std::pair<int, std::string>> pi0_path;
605 
606  K_path.emplace_back(0, std::string("B"));
607  K_path.emplace_back(0, std::string("D"));
608  K_path.emplace_back(0, std::string("K"));
609 
610  pi0_path.emplace_back(0, std::string("B"));
611  pi0_path.emplace_back(1, std::string("pi0"));
612 
613  EXPECT_NE(expected_hierarchies, selected_hierarchies);
614  expected_hierarchies.push_back(K_path);
615  expected_hierarchies.push_back(pi0_path);
616  EXPECT_EQ(expected_hierarchies, selected_hierarchies);
617  }
618 }
Belle2::DataStore::Instance
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
Belle2::DataStore::setInitializeActive
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
Belle2::DecayDescriptor::isIgnoreNeutrino
bool isIgnoreNeutrino() const
Check if missing neutrinos shall be ignored.
Definition: DecayDescriptor.h:171
Belle2::DecayDescriptorParticle::getPDGCode
int getPDGCode() const
Return PDG code.
Definition: DecayDescriptorParticle.h:89
Belle2::DecayDescriptor::isIgnoreGamma
bool isIgnoreGamma() const
Check if missing gammas shall be ignored.
Definition: DecayDescriptor.h:176
Belle2::DecayDescriptor::getSelectionNames
std::vector< std::string > getSelectionNames()
Return list of human readable names of selected particles.
Definition: DecayDescriptor.cc:343
Belle2::DecayDescriptorParticle::isIgnoreDecayInFlight
bool isIgnoreDecayInFlight() const
Check if decayInFlight shall be ignored.
Definition: DecayDescriptorParticle.h:109
Belle2::DecayDescriptor::init
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
Definition: DecayDescriptor.cc:47
Belle2::DecayDescriptorParticle::getLabel
std::string getLabel() const
The label of this particle, "default" returned, when no label set.
Definition: DecayDescriptorParticle.h:84
Belle2::DataStore::reset
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
Belle2::DecayDescriptorParticle::getFullName
std::string getFullName() const
returns the full name of the particle full_name = name:label
Definition: DecayDescriptorParticle.h:69
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::DecayDescriptor::getSelectionParticles
std::vector< const Particle * > getSelectionParticles(const Particle *particle)
Get a vector of pointers with selected daughters in the decay tree.
Definition: DecayDescriptor.cc:284
Belle2::Particle::appendDaughter
void appendDaughter(const Particle *daughter, const bool updateType=true)
Appends index of daughter to daughters index array.
Definition: Particle.cc:633
Belle2::DecayDescriptorParticle::isIgnoreMisID
bool isIgnoreMisID() const
Check if misID shall be ignored.
Definition: DecayDescriptorParticle.h:104
Belle2::DecayDescriptorParticle::isSelected
bool isSelected() const
Is the particle selected in the decay string?
Definition: DecayDescriptorParticle.h:79
Belle2::DecayDescriptor::getDaughter
const DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
Definition: DecayDescriptor.h:146
Belle2::DecayDescriptor::getNDaughters
int getNDaughters() const
return number of direct daughters.
Definition: DecayDescriptor.h:141
Belle2::TEST
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
Definition: utilityFunctions.cc:18
Belle2::DecayDescriptor::isIgnoreBrems
bool isIgnoreBrems() const
Check if added Brems gammas shall be ignored.
Definition: DecayDescriptor.h:181
Belle2::DecayDescriptorParticle::getName
std::string getName() const
evt.pdl name of the particle.
Definition: DecayDescriptorParticle.h:62
Belle2::DecayDescriptorParticle::isUnspecified
bool isUnspecified() const
Is the particle unspecified?
Definition: DecayDescriptorParticle.h:99
Belle2::Particle
Class to store reconstructed particles.
Definition: Particle.h:77
Belle2::DecayDescriptor::isIgnoreIntermediate
bool isIgnoreIntermediate() const
Check if intermediate resonances/particles shall be ignored.
Definition: DecayDescriptor.h:161
Belle2::DecayDescriptor
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
Definition: DecayDescriptor.h:43
Belle2::StoreArray< Particle >
Belle2::DecayDescriptor::isIgnoreRadiatedPhotons
bool isIgnoreRadiatedPhotons() const
Check if additional radiated photons shall be ignored.
Definition: DecayDescriptor.h:156
Belle2::DecayDescriptor::isIgnoreMassive
bool isIgnoreMassive() const
Check if missing massive final state particles shall be ignored.
Definition: DecayDescriptor.h:166
Belle2::DecayDescriptor::getMother
const DecayDescriptorParticle * getMother() const
return mother.
Definition: DecayDescriptor.h:136
Belle2::DecayDescriptor::getHierarchyOfSelected
std::vector< std::vector< std::pair< int, std::string > > > getHierarchyOfSelected()
Function to get hierarchy of selected particles and their names (for python use)
Definition: DecayDescriptor.cc:394