Belle II Software  release-08-01-10
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(std::string{"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(std::string{"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  std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"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(std::string{"@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(std::string{"^@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(std::string{"@^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  // @ can be attached to a daughter
245  DecayDescriptor dd4;
246  initok = dd4.init(std::string{"B0:Xsdee -> @Xsd e+:loose e-:loose"});
247  EXPECT_EQ(initok, true);
248  ASSERT_NE(dd4.getMother(), nullptr);
249  EXPECT_EQ(dd4.getMother()->isUnspecified(), false);
250  EXPECT_EQ(dd4.getMother()->isSelected(), false);
251  EXPECT_EQ(dd4.getDaughter(0)->getMother()->getName(), "Xsd");
252  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isUnspecified(), true);
253  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isSelected(), false);
254 
255  // Both selectors, @ and ^, can be used at the same time
256  DecayDescriptor dd5;
257  initok = dd5.init(std::string{"B0:Xsdee -> ^@Xsd e+:loose e-:loose"});
258  EXPECT_EQ(initok, true);
259  EXPECT_EQ(dd5.getDaughter(0)->getMother()->getName(), "Xsd");
260  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isUnspecified(), true);
261  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isSelected(), true);
262 
263  DecayDescriptor dd6;
264  initok = dd6.init(std::string{"B0:Xsdee -> @^Xsd e+:loose e-:loose"});
265  EXPECT_EQ(initok, true);
266  EXPECT_EQ(dd6.getDaughter(0)->getMother()->getName(), "Xsd");
267  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isUnspecified(), true);
268  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isSelected(), true);
269 
270  }
271 
272  TEST(DecayDescriptorTest, GrammarWithNestedDecay)
273  {
274  // ... means accept missing massive
275  DecayDescriptor dd1;
276  bool initok = dd1.init(std::string{"B0:candidates =direct=> [D-:pi =norad=> pi-:loose ... ?gamma] e+:loose ?nu ?addbrems"});
277  EXPECT_EQ(initok, true);
278  EXPECT_EQ(dd1.isIgnoreRadiatedPhotons(), true);
279  EXPECT_EQ(dd1.isIgnoreIntermediate(), false);
280  EXPECT_EQ(dd1.isIgnoreMassive(), false);
281  EXPECT_EQ(dd1.isIgnoreNeutrino(), true);
282  EXPECT_EQ(dd1.isIgnoreGamma(), false);
283  EXPECT_EQ(dd1.isIgnoreBrems(), true);
284 
285  const DecayDescriptor* dd1_D = dd1.getDaughter(0);
286  EXPECT_EQ(dd1_D->getMother()->getName(), "D-");
287  EXPECT_EQ(dd1_D->isIgnoreRadiatedPhotons(), false);
288  EXPECT_EQ(dd1_D->isIgnoreIntermediate(), true);
289  EXPECT_EQ(dd1_D->isIgnoreMassive(), true);
290  EXPECT_EQ(dd1_D->isIgnoreNeutrino(), false);
291  EXPECT_EQ(dd1_D->isIgnoreGamma(), true);
292  EXPECT_EQ(dd1_D->isIgnoreBrems(), false);
293 
294  }
295 
296 
297  TEST(DecayDescriptorTest, SelectionParticles)
298  {
299  DecayDescriptor dd1;
300  bool initok = dd1.init(std::string{"B0:B2Dzpipi -> [D0 -> ^K+:loose pi-:loose] pi+:loose pi-:loose"});
301  EXPECT_EQ(initok, true);
302  std::vector<std::string> names = dd1.getSelectionNames();
303  std::vector<int> pdgs = dd1.getSelectionPDGCodes();
304  ASSERT_EQ(names.size(), 1);
305  EXPECT_EQ(names[0], "B0_D0_K");
306  ASSERT_EQ(pdgs.size(), 1);
307  EXPECT_EQ(pdgs[0], 321);
308 
309  // add another selection particle to an already existing decay descriptor
310  // not sure exactly who is using this feature, but might as well test it.
311  initok = dd1.init(std::string{"B0:B2Dzpipi -> [D0 -> K+:loose ^pi-:loose] pi+:loose pi-:loose"});
312  EXPECT_EQ(initok, true);
313  names = dd1.getSelectionNames();
314  pdgs = dd1.getSelectionPDGCodes();
315  ASSERT_EQ(names.size(), 2);
316  EXPECT_EQ(names[0], "B0_D0_K");
317  EXPECT_EQ(names[1], "B0_D0_pi");
318  ASSERT_EQ(pdgs.size(), 2);
319  EXPECT_EQ(pdgs[0], 321);
320  EXPECT_EQ(pdgs[1], -211);
321 
322  // more complex decay string with multiple particles of the same type
323  DecayDescriptor dd2;
324  initok = dd2.init(std::string{"vpho:complex -> [D0 -> ^K+:loose pi-:loose] ^e+:loose ^e-:loose ^gamma:loose"});
325  EXPECT_EQ(initok, true);
326  names = dd2.getSelectionNames();
327  pdgs = dd2.getSelectionPDGCodes();
328  ASSERT_EQ(names.size(), 4);
329  EXPECT_EQ(names[0], "vpho_D0_K");
330  EXPECT_EQ(names[1], "vpho_e0");
331  EXPECT_EQ(names[2], "vpho_e1");
332  EXPECT_EQ(names[3], "vpho_gamma");
333  ASSERT_EQ(pdgs.size(), 4);
334  EXPECT_EQ(pdgs[0], 321);
335  EXPECT_EQ(pdgs[1], -11);
336  EXPECT_EQ(pdgs[2], 11);
337  EXPECT_EQ(pdgs[3], 22);
338  }
339 
340  TEST(DecayDescriptorTest, MisIDandDecayInFlightGrammar)
341  {
342  // MisID is ignored for a daughter which has (misID) in the head
343  DecayDescriptor dd1;
344  bool initok = dd1.init(std::string{"B0:sig -> (misID)K+:loose pi-:loose"});
345  EXPECT_EQ(initok, true);
346  ASSERT_NE(dd1.getMother(), nullptr);
347  EXPECT_EQ(dd1.getMother()->getName(), "B0");
348  EXPECT_EQ(dd1.getMother()->isIgnoreMisID(), false);
349  EXPECT_EQ(dd1.getMother()->isIgnoreDecayInFlight(), false);
350  ASSERT_NE(dd1.getDaughter(0), nullptr);
351  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getName(), "K+");
352  EXPECT_EQ(dd1.getDaughter(0)->getMother()->isIgnoreMisID(), true);
353  EXPECT_EQ(dd1.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
354  ASSERT_NE(dd1.getDaughter(1), nullptr);
355  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getName(), "pi-");
356  EXPECT_EQ(dd1.getDaughter(1)->getMother()->isIgnoreMisID(), false);//
357  EXPECT_EQ(dd1.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
358 
359  DecayDescriptor dd2;
360  initok = dd2.init(std::string{"B0:sig -> K+:loose (misID)pi-:loose"});
361  EXPECT_EQ(initok, true);
362  ASSERT_NE(dd2.getDaughter(0), nullptr);
363  EXPECT_EQ(dd2.getDaughter(0)->getMother()->getName(), "K+");
364  EXPECT_EQ(dd2.getDaughter(0)->getMother()->isIgnoreMisID(), false);//
365  EXPECT_EQ(dd2.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
366  ASSERT_NE(dd2.getDaughter(1), nullptr);
367  EXPECT_EQ(dd2.getDaughter(1)->getMother()->getName(), "pi-");
368  EXPECT_EQ(dd2.getDaughter(1)->getMother()->isIgnoreMisID(), true);
369  EXPECT_EQ(dd2.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
370 
371  DecayDescriptor dd3;
372  initok = dd3.init(std::string{"B0:sig -> (misID)K+:loose (misID)pi-:loose"});
373  EXPECT_EQ(initok, true);
374  ASSERT_NE(dd3.getDaughter(0), nullptr);
375  EXPECT_EQ(dd3.getDaughter(0)->getMother()->getName(), "K+");
376  EXPECT_EQ(dd3.getDaughter(0)->getMother()->isIgnoreMisID(), true);
377  EXPECT_EQ(dd3.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
378  ASSERT_NE(dd3.getDaughter(1), nullptr);
379  EXPECT_EQ(dd3.getDaughter(1)->getMother()->getName(), "pi-");
380  EXPECT_EQ(dd3.getDaughter(1)->getMother()->isIgnoreMisID(), true);
381  EXPECT_EQ(dd3.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);
382 
383  // DecayInFlight is ignored for a daughter which has (decay) in the head
384  DecayDescriptor dd4;
385  initok = dd4.init(std::string{"B0:sig -> (decay)K+:loose pi-:loose"});
386  EXPECT_EQ(initok, true);
387  ASSERT_NE(dd4.getDaughter(0), nullptr);
388  EXPECT_EQ(dd4.getDaughter(0)->getMother()->getName(), "K+");
389  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isIgnoreMisID(), false);
390  EXPECT_EQ(dd4.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
391  ASSERT_NE(dd4.getDaughter(1), nullptr);
392  EXPECT_EQ(dd4.getDaughter(1)->getMother()->getName(), "pi-");
393  EXPECT_EQ(dd4.getDaughter(1)->getMother()->isIgnoreMisID(), false);
394  EXPECT_EQ(dd4.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), false);//
395 
396  DecayDescriptor dd5;
397  initok = dd5.init(std::string{"B0:sig -> K+:loose (decay)pi-:loose"});
398  EXPECT_EQ(initok, true);
399  ASSERT_NE(dd5.getDaughter(0), nullptr);
400  EXPECT_EQ(dd5.getDaughter(0)->getMother()->getName(), "K+");
401  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isIgnoreMisID(), false);
402  EXPECT_EQ(dd5.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);//
403  ASSERT_NE(dd5.getDaughter(1), nullptr);
404  EXPECT_EQ(dd5.getDaughter(1)->getMother()->getName(), "pi-");
405  EXPECT_EQ(dd5.getDaughter(1)->getMother()->isIgnoreMisID(), false);
406  EXPECT_EQ(dd5.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
407 
408  DecayDescriptor dd6;
409  initok = dd6.init(std::string{"B0:sig -> (decay)K+:loose (decay)pi-:loose"});
410  EXPECT_EQ(initok, true);
411  ASSERT_NE(dd6.getDaughter(0), nullptr);
412  EXPECT_EQ(dd6.getDaughter(0)->getMother()->getName(), "K+");
413  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isIgnoreMisID(), false);
414  EXPECT_EQ(dd6.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
415  ASSERT_NE(dd6.getDaughter(1), nullptr);
416  EXPECT_EQ(dd6.getDaughter(1)->getMother()->getName(), "pi-");
417  EXPECT_EQ(dd6.getDaughter(1)->getMother()->isIgnoreMisID(), false);
418  EXPECT_EQ(dd6.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
419 
420  // @, ^, (misID), and (decay) can be used at the same time
421  DecayDescriptor dd7;
422  initok = dd7.init(std::string{"B0:sig -> (misID)(decay)K+:loose (decay)(misID)pi-:loose"});
423  EXPECT_EQ(initok, true);
424  ASSERT_NE(dd7.getDaughter(0), nullptr);
425  EXPECT_EQ(dd7.getDaughter(0)->getMother()->getName(), "K+");
426  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isSelected(), false);
427  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isUnspecified(), false);
428  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isIgnoreMisID(), true);
429  EXPECT_EQ(dd7.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
430  ASSERT_NE(dd7.getDaughter(1), nullptr);
431  EXPECT_EQ(dd7.getDaughter(1)->getMother()->getName(), "pi-");
432  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isSelected(), false);
433  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isUnspecified(), false);
434  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isIgnoreMisID(), true);
435  EXPECT_EQ(dd7.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
436 
437  DecayDescriptor dd8;
438  initok = dd8.init(std::string{"B0:sig -> ^(misID)K+:loose (decay)@pi-:loose"});
439  EXPECT_EQ(initok, true);
440  ASSERT_NE(dd8.getDaughter(0), nullptr);
441  EXPECT_EQ(dd8.getDaughter(0)->getMother()->getName(), "K+");
442  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isSelected(), true);
443  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isUnspecified(), false);
444  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isIgnoreMisID(), true);
445  EXPECT_EQ(dd8.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), false);
446  ASSERT_NE(dd8.getDaughter(1), nullptr);
447  EXPECT_EQ(dd8.getDaughter(1)->getMother()->getName(), "pi-");
448  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isSelected(), false);
449  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isUnspecified(), true);
450  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isIgnoreMisID(), false);
451  EXPECT_EQ(dd8.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
452 
453  DecayDescriptor dd9;
454  initok = dd9.init(std::string{"B0:sig -> ^@(misID)(decay)K+:loose (decay)@^(misID)pi-:loose"});
455  EXPECT_EQ(initok, true);
456  ASSERT_NE(dd9.getDaughter(0), nullptr);
457  EXPECT_EQ(dd9.getDaughter(0)->getMother()->getName(), "K+");
458  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isSelected(), true);
459  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isUnspecified(), true);
460  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isIgnoreMisID(), true);
461  EXPECT_EQ(dd9.getDaughter(0)->getMother()->isIgnoreDecayInFlight(), true);
462  ASSERT_NE(dd9.getDaughter(1), nullptr);
463  EXPECT_EQ(dd9.getDaughter(1)->getMother()->getName(), "pi-");
464  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isSelected(), true);
465  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isUnspecified(), true);
466  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isIgnoreMisID(), true);
467  EXPECT_EQ(dd9.getDaughter(1)->getMother()->isIgnoreDecayInFlight(), true);
468 
469  }
470 
471  TEST(DecayDescriptorTest, BadLabelTest)
472  {
473  // use of illegal characters in labels
474  DecayDescriptor dd1;
475  bool initok = dd1.init(std::string{"B0:lab[el -> K+:loose pi-:loose"});
476  EXPECT_EQ(initok, false);
477  EXPECT_EQ(dd1.getMother()->getName(), "");
478  EXPECT_EQ(dd1.getMother()->getLabel(), "");
479 
480  DecayDescriptor dd2;
481  initok = dd2.init(std::string{"B0:lab^el -> K+:loose pi-:loose"});
482  EXPECT_EQ(initok, false);
483  EXPECT_EQ(dd2.getMother()->getName(), "");
484  EXPECT_EQ(dd2.getMother()->getLabel(), "");
485 
486  DecayDescriptor dd3;
487  initok = dd3.init(std::string{"B0:lab]el -> K+:loose pi-:loose"});
488  EXPECT_EQ(initok, false);
489  EXPECT_EQ(dd3.getMother()->getName(), "");
490  EXPECT_EQ(dd3.getMother()->getLabel(), "");
491 
492  DecayDescriptor dd4;
493  initok = dd4.init(std::string{"B0:lab>el -> K+:loose pi-:loose"});
494  EXPECT_EQ(initok, false);
495  EXPECT_EQ(dd4.getMother()->getName(), "");
496  EXPECT_EQ(dd4.getMother()->getLabel(), "");
497 
498  DecayDescriptor dd5;
499  initok = dd5.init(std::string{"B0:lab:el -> K+:loose pi-:loose"});
500  EXPECT_EQ(initok, false);
501  EXPECT_EQ(dd5.getMother()->getName(), "");
502  EXPECT_EQ(dd5.getMother()->getLabel(), "");
503  }
504 
505  TEST(DecayDescriptorTest, UnicodeTest)
506  {
507  // this is broken with boost 1.72, still need to investigate
508  return;
509  // use of unicode characters in labels
510  const std::string weird = "⨔π⁰=πŸ–ΌπŸ”°";
511  DecayDescriptor dd1;
512  bool initok = dd1.init(std::string{"B0:" + weird + " -> K+:πŸ’©πŸ˜œ pi-:πŸ’―πŸ†πŸ’¦"});
513  ASSERT_EQ(initok, true);
514  EXPECT_EQ(dd1.getMother()->getName(), "B0");
515  EXPECT_EQ(dd1.getMother()->getLabel(), weird);
516  ASSERT_EQ(dd1.getNDaughters(), 2);
517  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getName(), "K+");
518  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getName(), "pi-");
519  EXPECT_EQ(dd1.getDaughter(0)->getMother()->getLabel(), "πŸ’©πŸ˜œ");
520  EXPECT_EQ(dd1.getDaughter(1)->getMother()->getLabel(), "πŸ’―πŸ†πŸ’¦");
521  }
522 
523  TEST(DecayDescriptorTest, BadGrammarTest)
524  {
525  DecayDescriptor dd1;
526  bool initok = dd1.init(std::string{"B0:label ---> K+:loose pi-:loose"});
527  EXPECT_EQ(initok, false);
528 
529  DecayDescriptor dd2;
530  initok = dd2.init(std::string{"B0:label > K+:loose pi-:loose"});
531  EXPECT_EQ(initok, false);
532 
533  DecayDescriptor dd3;
534  initok = dd3.init(std::string{"B0:label -> K+::loose pi-:loose"});
535  EXPECT_EQ(initok, false);
536 
537  DecayDescriptor dd4;
538  initok = dd4.init(std::string{"B0:label K+:loose pi-:loose"});
539  EXPECT_EQ(initok, false);
540 
541  DecayDescriptor dd5;
542  initok = dd5.init(std::string{"B0:label <- K+:loose pi-:loose"});
543  EXPECT_EQ(initok, false);
544 
545  DecayDescriptor dd6;
546  initok = dd6.init(std::string{"B0:label => K+:loose pi-:loose"});
547  EXPECT_EQ(initok, false);
548 
549  DecayDescriptor dd7;
550  initok = dd7.init(std::string{"B0:label --> K+:loose pi-:loose"});
551  EXPECT_EQ(initok, false);
552 
553  DecayDescriptor dd8;
554  initok = dd8.init(std::string{"B0:label ==> K+:loose pi-:loose"});
555  EXPECT_EQ(initok, false);
556  }
557 
558  TEST(DecayDescriptorTest, B2ParticleInterface)
559  {
560  // need datastore for the particles StoreArray
562  StoreArray<Particle> particles;
563  particles.registerInDataStore();
565 
566  // mock up a composite Belle2::Particle
567  ROOT::Math::PxPyPzEVector zeroes(0, 0, 0, 0);
568  Particle* Kp = particles.appendNew(Particle(zeroes, 321)); // 0
569  Particle* pim1 = particles.appendNew(Particle(zeroes, -211)); // 1
570  Particle* pim2 = particles.appendNew(Particle(zeroes, -211)); // 2
571  Particle* pip = particles.appendNew(Particle(zeroes, 211)); // 3
572  Particle* D0 = particles.appendNew(Particle(zeroes, 421)); // 4
573  D0->appendDaughter(0);
574  D0->appendDaughter(1);
575  Particle* B0 = particles.appendNew(Particle(zeroes, 511)); // 5
576  B0->appendDaughter(4);
577  B0->appendDaughter(3);
578  B0->appendDaughter(2);
579 
580  // ---
581  DecayDescriptor dd;
582  bool initok = dd.init(std::string{"B0:B2Dzpipi -> [D0 -> K+:loose ^pi-:loose] ^pi+:loose pi-:loose"});
583  ASSERT_EQ(initok, true);
584 
585  std::vector<const Particle*> selectionparticles = dd.getSelectionParticles(B0);
586  EXPECT_EQ(selectionparticles.size(), 2);
587  EXPECT_EQ(selectionparticles[0], pim1);
588  EXPECT_EQ(selectionparticles[1], pip);
589 
590  EXPECT_B2ERROR(dd.getSelectionParticles(D0));
591 
592  EXPECT_B2WARNING(dd.getSelectionParticles(pip));
593  EXPECT_B2WARNING(dd.getSelectionParticles(Kp));
594  EXPECT_B2WARNING(dd.getSelectionParticles(pim1));
595  EXPECT_B2WARNING(dd.getSelectionParticles(pim2));
596 
597  EXPECT_EQ(dd.getSelectionParticles(D0).size(), 0);
598 
600  }
601 
602  TEST(DecayDescriptorTest, HierarchyDefinitionTest)
603  {
604  DecayDescriptor dd;
605  bool initok = dd.init(std::string{"B+ -> [ D+ -> ^K+ pi0 ] ^pi0"});
606  EXPECT_EQ(initok, true);
607 
608  auto selected_hierarchies = dd.getHierarchyOfSelected();
609 
610  std::vector<std::vector<std::pair<int, std::string>>> expected_hierarchies;
611  std::vector<std::pair<int, std::string>> K_path;
612  std::vector<std::pair<int, std::string>> pi0_path;
613 
614  K_path.emplace_back(0, std::string("B"));
615  K_path.emplace_back(0, std::string("D"));
616  K_path.emplace_back(0, std::string("K"));
617 
618  pi0_path.emplace_back(0, std::string("B"));
619  pi0_path.emplace_back(1, std::string("pi0"));
620 
621  EXPECT_NE(expected_hierarchies, selected_hierarchies);
622  expected_hierarchies.push_back(K_path);
623  expected_hierarchies.push_back(pi0_path);
624  EXPECT_EQ(expected_hierarchies, selected_hierarchies);
625  }
626 }
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleType pi0
neutral pion particle
Definition: Const.h:665
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:653
static const ParticleType photon
photon particle
Definition: Const.h:664
static const ChargedStable electron
electron particle
Definition: Const.h:650
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
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.
std::vector< int > getSelectionPDGCodes()
Return list of PDG codes of selected particles.
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:75
void appendDaughter(const Particle *daughter, const bool updateType=true, const int daughterProperty=c_Ordinary)
Appends index of daughter to daughters index array.
Definition: Particle.cc:680
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.