Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hepmc.py
Go to the documentation of this file.
1 #**** This file is a part of the HAMMER library
2 #**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
3 #**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
4 #**** Please note the MCnet academic guidelines; see GUIDELINES for details
5 
6 """
7 @package hammer
8 @file hepmc.py
9 @brief Define a simple HepMC text parser
10 """
11 
12 from math import sqrt
13 
14 class FourPosition:
15  def __init__(self, x=0.0, y=0.0, z=0.0, t=0.0):
16  self.t = t
17  self.x = x
18  self.y = y
19  self.z = z
20 
21  def distance(self, other = None):
22  if other == None:
23  return sqrt((self.x)**2.+(self.y)**2.+(self.z)**2.)
24  else:
25  return sqrt((other.x-self.x)**2.+(other.y-self.y)**2.+(other.z-self.z)**2.)
26 
27  def to_vector(self):
28  return [self.t, self.x, self.y, self.z]
29 
30  def __sub__(self, other):
31  return FourPosition(self.x-other.x, self.y-other.y, self.z-other.z, self.t-other.t)
32 
33  def __add__(self, other):
34  return FourPosition(self.x+other.x, self.y+other.y, self.z+other.z, self.t+other.t)
35 
36 class FourMomentum:
37  def __init__(self, px=0.0, py=0.0, pz=0.0, e=0.0):
38  self.e = e
39  self.px = px
40  self.py = py
41  self.pz = pz
42 
43  def mass2(self):
44  return self.e**2 - self.px**2 - self.py**2 - self.pz**2
45 
46  def mass(self):
47  return sqrt(self.e**2 - self.px**2 - self.py**2 - self.pz**2)
48 
49  def to_vector(self):
50  return [self.e, self.px, self.py, self.pz]
51 
52  def __sub__(self, other):
53  return FourMomentum(self.px-other.px, self.py-other.py, self.pz-other.pz, self.e-other.e)
54 
55  def __add__(self, other):
56  return FourMomentum(self.px+other.px, self.py+other.py, self.pz+other.pz, self.e+other.e)
57 
58  def p(self):
59  return sqrt(self.px**2 + self.py**2 + self.pz**2)
60 
61 class Particle:
62  def __init__(self, pdg=0, p=FourMomentum(), status_code=0, start_vertex=0, end_vertex=0):
63  self.pdg = pdg
64  self.status_code = status_code
65  self.p = p
66  self.start_vertex_code = start_vertex
67  self.end_vertex_code = end_vertex
68 
69  def start_vertex(self, event=None):
70  return event.vertices[self.start_vertex_code] if event else None
71 
72  def end_vertex(self, event=None):
73  if self.end_vertex_code in event.vertices.keys():
74  return event.vertices[self.end_vertex_code] if event else None
75  else:
76  return Vertex() if event else None
77 
78 
79 class Vertex:
80  def __init__(self, pos=FourPosition(), parents=[], children=[]):
81  self.pos = pos
82  self.parents = set([parent for parent in parents if parent > 0])
83  self.children = set([child for child in children if child > 0])
84 
85  def add_parents(self, parents=[]):
86  [self.parents.add(parent) for parent in parents if parent > 0]
87 
88  def add_children(self, children=[]):
89  [self.children.add(child) for child in children if child > 0]
90 
91  def in_particles(self, event=None):
92  if event:
93  return [event.particles[bar_code] for bar_code in self.parents]
94  else:
95  return []
96 
97  def out_particles(self, event=None):
98  if event:
99  return [event.particles[bar_code] for bar_code in self.children]
100  else:
101  return []
102 
103  def distance(self, other=None):
104  return self.pos.distance(other.pos) if other is not None else 0.
105 
106 class Event:
107  def __init__(self, number = 0, process_id = 0, weights = []):
108  self.number = number
109  self.weights = weights
110  self.process_id = process_id
111  self.units = [None, None]
112  self.cross_section = [None, None]
113  self.particles = {}
114  self.vertices = {}
115 
116 
117 class HepMCParser:
118  def __init__(self, filename):
119  self.version = None
120  self._file = open(filename)
121  self._line = None
122  status = True
123  while status:
124  status = self._read_hepmc_line()
125  if status and self._line.startswith("HepMC::Version"):
126  self.version = self._line.split()[1]
127  break
128  while status and not self._line.startswith("HepMC::IO_GenEvent-START_EVENT_LISTING"):
129  self._read_hepmc_line()
130 
131  def _read_hepmc_line(self):
132  self._line = self._file.readline()
133  if not self._line:
134  return False
135  self._line = self._line.strip(" \n")
136  return True
137 
138  def read_event(self):
139  if not self._line or self._line.startswith("HepMC::IO_GenEvent-END_EVENT_LISTING"):
140  return None
141  while self._line.startswith("HepMC"):
142  self._read_hepmc_line()
143  if not self._line.startswith("E "):
144  return None
145  number, process_id, num_vertices, weights = self._parse_event_line()
146  event = Event(number, process_id, weights)
147  while self._read_hepmc_line() and not self._line.startswith("V "):
148  if self._line.startswith("U "):
149  event.units = self._parse_units()
150  elif self._line.startswith("C "):
151  event.cross_section = self._parse_cross_section()
152  in_particles = {}
153  for v_count in range(num_vertices):
154  v_code, vertex, num_in_particles, num_out_particles = self._parse_vertex()
155  in_list = []
156  out_list = []
157  for p_count in range(num_in_particles):
158  if self._read_hepmc_line():
159  p_code, particle, out_v_code = self._parse_particle()
160  event.particles.update({p_code: particle})
161  in_list.append(p_code)
162  vertex.add_parents(in_list)
163  for p_count in range(num_out_particles):
164  if self._read_hepmc_line():
165  p_code, particle, out_v_code = self._parse_particle(v_code)
166  event.particles.update({p_code: particle})
167  out_list.append(p_code)
168  if out_v_code != 0:
169  try:
170  in_particles[out_v_code].append(p_code)
171  except KeyError:
172  in_particles.update({ out_v_code: [p_code]})
173  vertex.add_children(out_list)
174  event.vertices.update({v_code: vertex})
175  self._read_hepmc_line()
176  for key, value in in_particles.items():
177  event.vertices[key].add_parents(value)
178  return event
179 
180  def _parse_cross_section(self):
181  tokens = self._line.split()
182  return [float(x) for x in tokens[1:3]]
183 
184  def _parse_event_line(self):
185  tokens = self._line.split()
186  num_seeds = int(tokens[11])
187  return int(tokens[1]), int(tokens[6]), int(tokens[8]), [float(x) for x in tokens[13+num_seeds:]]
188 
189  def _parse_units(self):
190  tokens = self._line.split()
191  return tokens[1:3]
192 
193  def _parse_vertex(self):
194  tokens = self._line.split()
195  code = -int(tokens[1])
196  pos = [float(x) for x in tokens[3:7]]
197  v = Vertex(FourPosition(*pos))
198  return code, v, int(tokens[7]), int(tokens[8])
199 
200  def _parse_particle(self, start_vertex_code=0):
201  tokens = self._line.split()
202  mom = [float(x) for x in tokens[3:7]]
203  end_v = -int(tokens[11])
204  p = Particle(int(tokens[2]), FourMomentum(*mom), int(tokens[8]), start_vertex_code, end_v)
205  return int(tokens[1]), p, end_v