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