13 from itertools
import combinations
14 from variables
import variables
as vm
17 def get_object_list(pointerVec):
19 Workaround to avoid memory problems in basf2.
22 pointerVec: Input particle list.
25 list: Output python list.
27 from ROOT
import Belle2
31 pointerVec.getListSize()
36 objList.append(pointerVec[i])
40 def pdg_to_lca_converter(pdg):
42 Converts PDG code to LCAS classes.
44 .. tip:: If you want to modify the LCAS classes, it's here.
45 Don't forget to update the number of edge classes accordingly in the yaml file.
48 pdg (int): PDG code to convert.
51 int or None: Corresponding LCAS class, or None if PDG not present in ``pdg_lca_match``.
71 if pdg
in pdg_lca_match:
72 return pdg_lca_match[pdg]
77 def _update_levels(levels, hist, pdg):
79 Assigns LCAS level to each particle in the decay tree.
81 Arguments are automatically set.
83 for i, n
in enumerate(hist):
84 if n
in levels.keys():
87 lca = pdg_to_lca_converter(pdg[n])
91 for j
in range(i + 1):
92 lca = pdg_to_lca_converter(pdg[hist[i - j]])
110 Recursive function to traverse down to the leaves saving the history.
113 particle: The current particle being inspected.
114 Other arguments are automatically set.
117 neutrino_pdgs = [12, 14, 16, 18]
121 if (abs(particle.getPDG())
in neutrino_pdgs)
and particle.isPrimaryParticle():
125 hist = copy.deepcopy(hist)
126 leaf_hist = copy.deepcopy(leaf_hist)
127 leaf_pdg = copy.deepcopy(leaf_pdg)
128 levels = copy.deepcopy(levels)
129 pdg = copy.deepcopy(pdg)
140 prim_no_prim_daughters = (
142 [d
for d
in get_object_list(particle.getDaughters())
if d.isPrimaryParticle()]
151 (particle.getNDaughters() == 0)
152 or prim_no_prim_daughters
155 if abs(particle.getPDG())
not in neutrino_pdgs
and not (
156 particle.getPDG() == 22
and particle.getEnergy() < 1e-4
159 leaf_hist[particle.getArrayIndex()] = hist
160 leaf_pdg[particle.getArrayIndex()] = particle.getPDG()
164 levels = _update_levels(levels, hist, pdg)
169 particle.getNDaughters() != 0
170 )
and not prim_no_prim_daughters:
172 if particle.isPrimaryParticle():
173 hist.append(particle.getArrayIndex())
175 pdg[particle.getArrayIndex()] = particle.getPDG()
178 daughters = get_object_list(particle.getDaughters())
179 for daughter
in daughters:
207 Save Lowest Common Ancestor matrix of each MC Particle in the given list.
210 particle_lists (list): Name of particle lists to save features of.
211 features (list): List of features to save for each particle.
212 mcparticle_list (str): Name of particle list to build LCAs from (will use as root).
213 output_file (str): Path to output file to save.
243 Called once at the beginning.
245 from ROOT
import Belle2, TFile, TTree
253 self.
treetree = TTree(
"Tree",
"tree")
257 self.
treetree.Branch(
"event", self.
event_numevent_num,
"event/I")
259 self.
isBisB = np.zeros(1, dtype=bool)
260 self.
treetree.Branch(
"isB", self.
isBisB,
"isB/b")
267 self.
truth_dicttruth_dict[f
"n_LCA_leaves_{i}"] = np.zeros(1, dtype=np.int32)
268 self.
truth_dicttruth_dict[f
"LCA_leaves_{i}"] = np.zeros(
271 self.
treetree.Branch(
273 self.
truth_dicttruth_dict[f
"n_LCA_leaves_{i}"],
274 f
"n_LCA_leaves_{i}/I",
276 self.
treetree.Branch(
279 f
"LCA_leaves_{i}[n_LCA_leaves_{i}]/I",
282 self.
truth_dicttruth_dict[f
"n_LCA_{i}"] = np.zeros(1, dtype=np.int32)
283 self.
truth_dicttruth_dict[f
"LCAS_{i}"] = np.zeros(
286 self.
treetree.Branch(f
"n_LCA_{i}", self.
truth_dicttruth_dict[f
"n_LCA_{i}"], f
"n_LCA_{i}/I")
287 self.
treetree.Branch(
288 f
"LCAS_{i}", self.
truth_dicttruth_dict[f
"LCAS_{i}"], f
"LCAS_{i}[n_LCA_{i}]/b"
294 self.
treetree.Branch(
"n_particles", self.
n_particlesn_particles,
"n_particles/I")
298 self.
treetree.Branch(
"primary", self.
primaryprimary,
"primary[n_particles]/O")
302 self.
treetree.Branch(
"leaves", self.
leavesleaves,
"leaves[n_particles]/I")
306 self.
treetree.Branch(
"b_index", self.
b_indexb_index,
"b_index[n_particles]/I")
312 self.
treetree.Branch(
313 f
"feat_{feat}", self.
feat_dictfeat_dict[feat], f
"feat_{feat}[n_particles]/F"
318 self.
treetree.Branch(
"mcPDG", self.
mc_pdgmc_pdg,
"mcPDG[n_particles]/F")
322 Resets the value of the LCA to 0.
324 for p_index
in [1, 2]:
326 self.
truth_dicttruth_dict[f
"n_LCA_leaves_{p_index}"][0] *= 0
328 self.
truth_dicttruth_dict[f
"n_LCA_{p_index}"][0] *= 0
332 Called for each event.
334 from ROOT.Belle2
import PyStoreObj
355 if p_list.getListSize() > 0:
356 for part
in p_list.obj():
358 mcp = part.getMCParticle()
363 array_index = 1
if self.
isBisB[0] == 0
else mcp.getArrayIndex()
382 lcas = np.zeros([len(lcas_leaf_hist), len(lcas_leaf_hist)])
384 for x, y
in combinations(enumerate(lcas_leaf_hist), 2):
385 lcas_intersection = [
386 i
for i
in lcas_leaf_hist[x[1]]
if i
in lcas_leaf_hist[y[1]]
388 lcas[x[0], y[0]] = lcas_levels[lcas_intersection[-1]]
389 lcas[y[0], x[0]] = lcas_levels[lcas_intersection[-1]]
391 self.
truth_dicttruth_dict[f
"LCAS_{array_index}"][: lcas.size] = lcas.flatten()
393 self.
truth_dicttruth_dict[f
"n_LCA_leaves_{array_index}"][0] = len(lcas_leaf_hist.keys())
394 self.
truth_dicttruth_dict[f
"LCA_leaves_{array_index}"][
395 : len(lcas_leaf_hist.keys())
396 ] = list(lcas_leaf_hist.keys())
398 self.
truth_dicttruth_dict[f
"n_LCA_{array_index}"][0] = lcas.size
402 evt_feats = {f: []
for f
in self.
featuresfeatures}
417 p_list = PyStoreObj(p_list_name)
419 for particle
in p_list.obj():
421 b_index = int(vm.evaluate(
"ancestorBIndex", particle))
424 p_index = particle.getMCParticle().getArrayIndex()
425 p_primary = particle.getMCParticle().isPrimaryParticle()
427 mc_pdg = particle.getMCParticle().getPDG()
433 evt_leaf_dict[
"primary"].append(p_primary)
434 evt_leaf_dict[
"leaves"].append(p_index)
435 evt_leaf_dict[
"b_index"].append(b_index)
436 evt_leaf_dict[
"mc_pdg"].append(mc_pdg)
438 evt_feats[feat].append(vm.evaluate(feat, particle))
440 n_particles = len(evt_leaf_dict[
"primary"])
443 self.
primaryprimary[:n_particles] = evt_leaf_dict[
"primary"]
444 self.
leavesleaves[:n_particles] = evt_leaf_dict[
"leaves"]
445 self.
b_indexb_index[:n_particles] = evt_leaf_dict[
"b_index"]
446 self.
mc_pdgmc_pdg[:n_particles] = evt_leaf_dict[
"mc_pdg"]
449 self.
feat_dictfeat_dict[feat][:n_particles] = evt_feats[feat]
ParticleList is a container class that stores a collection of Particle objects.
a (simplified) python wrapper for StoreObjPtr.
primary
Particle-is-primary flag.
isB
bool containing information whether we reconstruct B or Upsilon
features
Features to save.
truth_dict
Truth information.
max_particles
Max number of particles It doesn't actually matter what this is as long as it's bigger than the numbe...
root_outfile
ROOT output file.
output_file
Output file name.
n_particles
Number of particles.
particle_lists
Input particle lists.
def __init__(self, particle_lists, features, mcparticle_list, output_file)
feat_dict
Features dictionary.
mcparticle_list
MC particle list (Upsilon, B0, B+)