def decayTree(self, genparticles): db = TDatabasePDG() theString = "" for part in genparticles: if part.M1==-1 and part.M2==-1: theString += part.printDecay(db, genparticles) return theString
def __init__(self, filename, exclude_noise, save_plot, max_spill_count): self.filename = filename self.exclude_noise = exclude_noise self.save_plot = save_plot self.data_dir = os.path.dirname(self.filename) if not self.data_dir: self.data_dir = '.' self.file_basename = os.path.basename(self.filename) self.max_spill_count = max_spill_count self.pdg = TDatabasePDG() self.delta_x = 1.4 # mm self.delta_y = 8.6 # mm self.delta_z = 0. # mm # self.delta_x = 1375.9 # mm # self.delta_y = -67.5 # mm # self.delta_z = -14617.4 # mm self.angle_rotation_y_axis = -0.349 * pi / 180. # rad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ID - type Part ID - - px py pz - - vx vy vz 1=active """ # all the not useful fields will be filled with 99 from ROOT import TGenPhaseSpace, TLorentzVector, TDatabasePDG, TMath, TVector3 import math from random import random as rndm from array import array from random import gauss dbpdg = TDatabasePDG() # chose motherParticle PDGmother = 3122 MotherMass = dbpdg.GetParticle(PDGmother).Mass() # chose daughters PDGs = [2212, -211] DaughterMass = [dbpdg.GetParticle(i).Mass() for i in PDGs] # Settings # ======== NEVENTS = 50000 BeamPolarization = -1 # not useful
""" This module contains names for the various PDG particle ID codes. The names are the same as in EventKernel/PdtPdg.h. This module also contains a dictionary pdgid_names mapping ID codes back to printable strings, and a function pdgid_to_name to do this conversion. Similarly, root_names and pdgid_to_root_name translate to strings with root markup. """ from __future__ import absolute_import from ROOT import TDatabasePDG from pkg_resources import resource_filename import os db = TDatabasePDG() db.ReadPDGTable(resource_filename('rootpy', 'etc/pdg_table.txt')) def GetParticle(id): return db.GetParticle(id) # Table to translate from PDG IDs to printable strings. pdgid_names = {} # Table to translate from PDG IDs to strings with root markup. root_names = {} def id_to_name(id):
def print_evt(event_filter=">= 0"): pdg_db = TDatabasePDG() ev_df = df.Filter(f"fIndexMcCollisions {event_filter}") npy = ev_df.AsNumpy() print() lastmother = 0 for i, part_index in enumerate(npy["part_index"]): ev = npy["fIndexMcCollisions"][i] count("events", ev) if 0: m0 = npy["fMother0"][i] m1 = npy["fMother1"][i] d0 = npy["fDaughter0"][i] d1 = npy["fDaughter1"][i] else: m_arr = npy["fIndexArray_Mothers"][i] d_arr = npy["fIndexSlice_Daughters"][i] m_size = npy["fIndexArray_Mothers_size"][i] # print(m_size) # print("Mothers", m_arr) # print("Daughters", d_arr) if len(m_arr) == 0: m0 = -1 m1 = -1 else: m0 = m_arr[0] m1 = m_arr[int(m_size) - 1] d0 = d_arr[0] d1 = d_arr[1] # print(d_arr) pdg = npy["fPdgCode"][i] px = npy["fPx"][i] py = npy["fPy"][i] pz = npy["fPz"][i] eta = npy["eta"][i] is_ps = bool(npy["isPhysicalPrimary"][i]) is_pt = bool(npy["isProducedByTransport"][i]) process = npy["fStatusCode"][i] def getpname(pdg_code): p = pdg_db.GetParticle(int(pdg_code)) if p: p = p.GetName() else: p = "Undef" return p part = getpname(pdg) summary_line = f" ({part_index}) ev {ev} m0 {m0} m1 {m1}, d0 {d0} d1 {d1}, pdg {pdg} '{part}', physical primary {is_ps}, in transport {is_pt}, process {process}" if abs(pdg) not in [21, 2101, 2103, 2203, 1, 2, 3, 4, 5 ] and m0 > -1: if lastmother != m0 and count("mothers", m0): raise ValueError("Duplicate mothers for ", summary_line) lastmother = m0 if d1 > -1 and d0 > d1: if not continue_on_inconsistency: raise ValueError("d0 > d1:", summary_line) else: warning_msg("d0 > d1 for", part_index) def get_the_daughters(): idaughters = [] if d0 > -1 and d1 > -1: for j in range(d0, d1 + 1): entry = numpy.where(npy["part_index"] == j)[0] if len(entry) > 1: raise ValueError("Entry size is too high!") if len(entry) == 0: raise ValueError("Entry size is too low!") entry = entry[0] if 0: d_m0 = npy["fMother0"][entry] d_m1 = npy["fMother1"][entry] else: d_m0 = npy["fIndexArray_Mothers"][entry][0] d_m1 = npy["fIndexArray_Mothers"][entry][ int(npy["fIndexArray_Mothers_size"][entry]) - 1] if d_m0 != part_index and d_m1 != part_index: if not continue_on_inconsistency: raise ValueError("Daughter", j, "has a different mother!", "d_m0", d_m0, "d_m1", d_m1, "w.r.t.", part_index) else: warning_msg("Daughter", j, "has a different mother!", "d_m0", d_m0, "d_m1", d_m1, "w.r.t.", part_index) if d_m0 == d_m1 and 0: raise ValueError("Daughter has same mother!", d_m0, d_m1) idaughters.append(entry) if len(idaughters) == 0: warning_msg("Found no daughters") return idaughters # Checking that indices are increasing if sorted(idaughters) != idaughters: raise ValueError("Daughters are not in order!") # Checking that indices have no holes if idaughters != [*range(idaughters[0], idaughters[-1] + 1)]: raise ValueError("Daughters have hole in indices!", idaughters) return idaughters def daughters_pxpypz(daughters): d_px = 0 d_py = 0 d_pz = 0 if len(daughters) == 0: return None for j in daughters: d_px += npy["fPx"][j] d_py += npy["fPy"][j] d_pz += npy["fPz"][j] return d_px, d_py, d_pz def daughters_pdg(daughters): d_pdgs = [] for j in daughters: d_pdgs.append(npy["fPdgCode"][j]) return d_pdgs def check_momentum(daughters): d_p = daughters_pxpypz(daughters) if d_p is None: return m_p = [px, py, pz] m_p_d = {0: "Px", 1: "Py", 2: "Pz"} momentum_format = "(px={:.5f}, py={:.5f}, pz={:.5f})" for j in enumerate(m_p): if abs(j[1] - d_p[j[0]]) > 0.001: e_msg = [ "Non-closure in", m_p_d[j[0]], "=", momentum_format.format(*d_p) ] if not continue_on_inconsistency: raise ValueError(*e_msg) else: warning_msg(*e_msg) warning_msg(" mother =", momentum_format.format(*m_p)) def is_decay_channel(desired_pdg_codes, daughters, fill_counter=True, min_prongs=0, max_prongs=10): d_pdgs = daughters_pdg(daughters) if len(daughters) >= min_prongs and len( daughters) <= max_prongs: print(pdg, part, "decaying in", len(d_pdgs), "particles") for i, j in enumerate(d_pdgs): if 0: this_m0 = npy["fMother0"][daughters[i]] this_m1 = npy["fMother1"][daughters[i]] else: this_m0 = npy["fIndexArray_Mothers"][ daughters[i]][0] this_m1 = npy["fIndexArray_Mothers"][daughters[i]][ int(npy["fIndexArray_Mothers_size"][ daughters[i]]) - 1] print(" >", j, getpname(j), "index", daughters[i], npy["part_index"][daughters[i]], "m0", this_m0, "m1", this_m1, " -> physical primary", npy["isPhysicalPrimary"][daughters[i]]) if desired_pdg_codes is not None: for i in desired_pdg_codes: if i not in d_pdgs: return False if fill_counter: count( f"{bcolors.BOKGREEN} {pdg} {part} {bcolors.ENDC} in {d_pdgs}", part_index) return True extra = [] if m0 < 0 and m1 < 0 and d0 < 1 and d1 < 0: extra.append("Sterile") if d1 < 0 and d1 != d0: extra.append(bcolors.BWARNING + "Problematic" + bcolors.ENDC) if pdg in pdg_of_interest: extra.append(", px={:.3f} py={:.2f} pz={:.2f}".format( px, py, pz)) extra.append(", eta={:.4f}".format(eta)) extra.append(bcolors.BOKGREEN + "PDG of interest" + bcolors.ENDC) extra = " ".join(extra) extra = extra.strip() count(part, part_index) if verbose or pdg in pdg_of_interest: print(summary_line, extra) if pdg in pdg_of_interest: daughters = get_the_daughters() check_momentum(daughters) is_decay_channel(None, daughters=daughters, fill_counter=True)
def print_evt(event_filter=">= 0"): pdg_db = TDatabasePDG() ev_df = df.Filter(f"fMcCollisionsID {event_filter}") npy = ev_df.AsNumpy() print() lastmother = 0 for i, part_index in enumerate(npy["part_index"]): ev = npy["fMcCollisionsID"][i] count("events", ev) m0 = npy["fMother0"][i] m1 = npy["fMother1"][i] d0 = npy["fDaughter0"][i] d1 = npy["fDaughter1"][i] pdg = npy["fPdgCode"][i] px = npy["fPx"][i] py = npy["fPy"][i] pz = npy["fPz"][i] def getpname(pdg_code): p = pdg_db.GetParticle(int(pdg_code)) if p: p = p.GetName() else: p = "Undef" return p part = getpname(pdg) summary_line = f" ({part_index}) ev {ev} m0 {m0} m1 {m1}, d0 {d0} d1 {d1}, pdg {pdg} '{part}'" if abs(pdg) not in [21, 2101, 2103, 2203, 1, 2, 3, 4, 5 ] and m0 > -1: if lastmother != m0 and count("mothers", m0): raise ValueError("Duplicate mothers for ", summary_line) lastmother = m0 if d1 > -1 and d0 > d1: raise ValueError("d0 < d1:", summary_line) def daughters(): idaughters = [] if d0 > -1 and d1 > -1: for j in range(d0, d1 + 1): entry = numpy.where(npy["part_index"] == j)[0] if len(entry) > 1: raise ValueError("Entry size is too high!") if len(entry) == 0: raise ValueError("Entry size is too low!") entry = entry[0] d_m0 = npy["fMother0"][entry] d_m1 = npy["fMother1"][entry] if d_m0 != part_index and d_m1 != part_index: raise ValueError( "Daughter has a different mother!", d_m0, d_m1, "w.r.t.", part_index) if d_m0 == d_m1: raise ValueError("Daughter has same mother!", d_m0, d_m1) idaughters.append(entry) # Checking that indices are increasing if sorted(idaughters) != idaughters: raise ValueError("Daughters are not in order!") # Checking that indices have no holes if idaughters != [*range(idaughters[0], idaughters[-1] + 1)]: raise ValueError("Daughters have hole in indices!", idaughters) return idaughters def daughters_pxpypz(): d_px = 0 d_py = 0 d_pz = 0 d = daughters() for j in d: d_px += npy["fPx"][j] d_py += npy["fPy"][j] d_pz += npy["fPz"][j] return d_px, d_py, d_pz def daughters_pdg(): d = daughters() d_pdgs = [] for j in d: d_pdgs.append(npy["fPdgCode"][j]) return d_pdgs def check_momentum(): d_p = daughters_pxpypz() m_p = [px, py, pz] for j in enumerate(m_p): if (j[1] - d_p[j[0]]) > 0.001: raise ValueError("Wrong P", j, "with", d_p) def is_decay_channel(desired_pdg_codes, fill_counter=True, min_prongs=0, max_prongs=10): d = daughters() d_pdgs = daughters_pdg() if len(d) >= min_prongs and len(d) <= max_prongs: print(pdg, part, "decaying in") for i, j in enumerate(d_pdgs): print(" >", j, getpname(j), "index", d[i], npy["part_index"][d[i]], "m0", npy["fMother0"][d[i]], "m1", npy["fMother1"][d[i]]) if desired_pdg_codes is not None: for i in desired_pdg_codes: if i not in d_pdgs: return False if fill_counter: count( f"{bcolors.BOKGREEN} {pdg} {part} {bcolors.ENDC} in {d_pdgs}", part_index) return True extra = [] if m0 < 0 and m1 < 0 and d0 < 1 and d1 < 0: extra.append("Sterile") if d1 <= d0 and d1 > -1: extra.append(bcolors.BWARNING + "Problematic" + bcolors.ENDC) if pdg in pdg_of_interest: extra.append(bcolors.BOKGREEN + "PDG of interest" + bcolors.ENDC) extra = " ".join(extra) count(part, part_index) if verbose or pdg in pdg_of_interest: print(summary_line, extra) if pdg in pdg_of_interest: check_momentum() is_decay_channel(None, fill_counter=True)