Belle II Software  light-2212-foldex
copylists.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 import unittest
13 import uproot
14 import basf2 as b2
15 import b2test_utils as b2tu
16 import modularAnalysis as ma
17 from stdPi0s import stdPi0s
18 from stdV0s import stdKshorts
19 from variables import variables as vm
20 
21 
22 def dump_3_v2nts(names_of_three_lists, path):
23  """Dump each of the three vpho lists into a VariablesToNtuple on path"""
24  first, second, third = names_of_three_lists
25  vs = ['d0_mdstIndex', 'd0_p']
26  ma.variablesToNtuple("vpho:" + first, vs, treename=first, path=path)
27  ma.variablesToNtuple("vpho:" + second, vs, treename=second, path=path)
28  ma.variablesToNtuple("vpho:" + third, vs, treename=third, path=path)
29 
30 
31 def run_copylists():
32  """A simple basf2 analysis job to do some list copying"""
33 
34  # aliases for useful for manual debugging
35  vm.addAlias("d0_mdstIndex", "daughter(0, mdstIndex)")
36  vm.addAlias("d0_p", "daughter(0, p)")
37 
38  # analysis input
39  pa = b2.Path()
40  ma.inputMdst(b2.find_file("analysis/tests/mdst.root"), path=pa)
41  ma.fillParticleList("pi+", "", path=pa)
42  ma.fillParticleList("K+", "", path=pa)
43  stdPi0s('all', path=pa)
44  stdKshorts(path=pa)
45 
46  # first test: check that merging two lists with
47  # identical daughters removes duplicates
48  ma.reconstructDecay("vpho:a -> K+", "", path=pa, allowChargeViolation=True)
49  ma.reconstructDecay("vpho:b -> K+", "", path=pa, allowChargeViolation=True)
50  ma.copyLists("vpho:ab", ["vpho:a", "vpho:b"], path=pa)
51  dump_3_v2nts(["a", "b", "ab"], path=pa)
52 
53  # second test: check that two lists with different daughters (but from the
54  # same underlying mdst object) are included twice (as expected)
55  ma.reconstructDecay("vpho:c -> K+", "", path=pa, allowChargeViolation=True)
56  ma.reconstructDecay("vpho:d -> pi-", "", path=pa, allowChargeViolation=True)
57  ma.copyLists("vpho:cd", ["vpho:c", "vpho:d"], path=pa)
58  dump_3_v2nts(["c", "d", "cd"], path=pa)
59 
60  # third test: check that two lists with the same daughters in different
61  # orders don't double count
62  # (they are different Belle2::Particles but we should match them)
63  ma.reconstructDecay("vpho:e -> K+ pi-", "", path=pa)
64  ma.reconstructDecay("vpho:f -> pi- K+", "", path=pa)
65  ma.copyLists("vpho:ef", ["vpho:e", "vpho:f"], path=pa)
66  dump_3_v2nts(["e", "f", "ef"], path=pa)
67 
68  # fourth test: check that it is considered whose daughter a pi0 is when
69  # there are two charge-conjugated daughters
70  ma.reconstructDecay("tau+:pi -> pi+", "", dmID=0, path=pa)
71  ma.reconstructDecay("tau+:pipi0 -> pi+ pi0:all", "", dmID=1, path=pa)
72  # the pi0 is the daughter of the tau-
73  ma.reconstructDecay("vpho:g -> tau+:pi tau-:pipi0", "", path=pa, chargeConjugation=False)
74  # the pi0 is the daughter of the tau+
75  ma.reconstructDecay("vpho:h -> tau-:pi tau+:pipi0", "", path=pa, chargeConjugation=False)
76  # charge-conjugation has been turned off for the vpho lists above so the
77  # merged list should just be the sum
78  ma.copyLists("vpho:gh", ["vpho:g", "vpho:h"], path=pa)
79  dump_3_v2nts(["g", "h", "gh"], path=pa)
80 
81  # fifth test: check that it is considered whose daughter self-conjugated
82  # particles are if there are two charge-conjugated daughters
83  ma.reconstructDecay("tau+:KS0 -> pi+ K_S0:merged", "", dmID=0, path=pa)
84  ma.reconstructDecay("tau+:pi0 -> pi+ pi0:all", "", dmID=1, path=pa)
85  # the pi0 is the daughter of the tau-
86  ma.reconstructDecay("vpho:KS -> tau+:KS0 tau-:pi0", "", path=pa, chargeConjugation=False)
87  # the pi0 is the daughter of the tau+
88  ma.reconstructDecay("vpho:pi0 -> tau-:KS0 tau+:pi0", "", path=pa, chargeConjugation=False)
89  # charge-conjugation has been turned off for the vpho lists above so the
90  # merged list should just be the sum
91  ma.copyLists("vpho:KSpi0", ["vpho:KS", "vpho:pi0"], path=pa)
92  dump_3_v2nts(["KS", "pi0", "KSpi0"], path=pa)
93 
94  # sixth test: check that check of mother flavor can be turned off when identifying duplicates
95  ma.reconstructDecay("D0 -> K- pi+", "", dmID=0, chargeConjugation=False, path=pa)
96  ma.matchMCTruth("D0", path=pa)
97  ma.cutAndCopyList("D0:sig", "D0", "isSignal==1", path=pa)
98  ma.reconstructDecay("anti-D0:anti -> K- pi+", "", dmID=1, chargeConjugation=False, path=pa)
99  ma.matchMCTruth("anti-D0:anti", path=pa)
100  ma.cutAndCopyList("anti-D0:antisig", "anti-D0:anti", "isSignal==1", path=pa)
101  ma.mergeListsWithBestDuplicate("D0:ignore", ['D0', 'anti-D0:anti'], 'isSignal', path=pa,
102  preferLowest=False, ignoreMotherFlavor=True)
103  ma.copyLists("D0:flavor", ['D0', 'anti-D0:anti'], path=pa)
104  ma.variablesToNtuple("D0", ['isSignal', 'PDG'], treename="D0", path=pa)
105  ma.variablesToNtuple("anti-D0:anti", ['isSignal', 'PDG'], treename="anti", path=pa)
106  ma.variablesToNtuple("D0:ignore", ['isSignal', 'PDG'], treename="ignore", path=pa)
107  ma.variablesToNtuple("D0:flavor", ['isSignal', 'PDG'], treename="flavor", path=pa)
108 
109  b2tu.safe_process(pa, 1)
110 
111 
112 class TestCopyLists(unittest.TestCase):
113  """Analyse the output of ``run_copylists``"""
114 
115  def _count(self, listname):
116  """Open the ntuple output and count the number of entries in the list."""
117  df = uproot.open("ntuple.root")[listname].arrays(library="pd")
118  return len(df)
119 
121  """Merging two lists with identical daughters should not double count."""
122  self.assertEqual(self._count_count("a"), self._count_count("b"))
123  self.assertEqual(self._count_count("a"), self._count_count("ab"))
124  self.assertEqual(self._count_count("b"), self._count_count("ab"))
125 
127  """Merging two lists with different daughters but with the same mdst
128  object should include each of them twice."""
129  self.assertEqual(self._count_count("c"), self._count_count("d"))
130  self.assertEqual(self._count_count("c") + self._count_count("d"), self._count_count("cd"))
131 
133  """Merging two lists with daughters in a different order should not double count."""
134  self.assertEqual(self._count_count("e"), self._count_count("e"))
135  self.assertEqual(self._count_count("e"), self._count_count("ef"))
136 
138  """Self-conjugated particles can be daughters of both charge-conjugated mother particles.
139  Those multiple candidates are no duplicates and copying the particle list should not remove them."""
140  self.assertEqual(self._count_count("g") + self._count_count("h"), self._count_count("gh"))
141 
143  """Different self-conjugated particles are daughters of charge-conjugated mother particles.
144  The two mother particles have the same amount of daughters."""
145  self.assertEqual(self._count_count("KS") + self._count_count("pi0"), self._count_count("KSpi0"))
146 
148  """Particle lists can be merged ignoring the flavor of the mother particle. If both particle
149  lists decay into the same final state, the size of the combined list is identical to one
150  individual list. Otherwise, it's the sum of the two."""
151  self.assertEqual(self._count_count("D0"), self._count_count("ignore"))
152  self.assertEqual(self._count_count("D0") + self._count_count("anti"), self._count_count("flavor"))
153 
154 
155 if __name__ == "__main__":
156  with b2tu.clean_working_directory():
157  run_copylists()
158  unittest.main()
def test_different_association_of_neutrals_same_number_of_daughters(self)
Definition: copylists.py:142
def test_neutrals_in_decays_to_charge_conjugated_daughters(self)
Definition: copylists.py:137
def test_different_daughter_order(self)
Definition: copylists.py:132
def test_merge_two_lists_with_different_mdst_objects(self)
Definition: copylists.py:126
def _count(self, listname)
Definition: copylists.py:115
def test_merge_two_lists_with_identical_daughters(self)
Definition: copylists.py:120
def test_ignore_mother_flavor(self)
Definition: copylists.py:147