9 @brief Define a simple HepMC text parser 
   15     def __init__(self, x=0.0, y=0.0, z=0.0, t=0.0):
 
   21     def distance(self, other = None):
 
   23             return sqrt((self.x)**2.+(self.y)**2.+(self.z)**2.)
 
   25             return sqrt((other.x-self.x)**2.+(other.y-self.y)**2.+(other.z-self.z)**2.)
 
   28         return [self.t, self.x, self.y, self.z]
 
   30     def __sub__(self, other):
 
   31         return FourPosition(self.x-other.x, self.y-other.y, self.z-other.z, self.t-other.t)
 
   33     def __add__(self, other):
 
   34         return FourPosition(self.x+other.x, self.y+other.y, self.z+other.z, self.t+other.t)
 
   37     def __init__(self, px=0.0, py=0.0, pz=0.0, e=0.0):
 
   44         return self.e**2 - self.px**2 - self.py**2 - self.pz**2
 
   47         return sqrt(self.e**2 - self.px**2 - self.py**2 - self.pz**2)
 
   50         return [self.e, self.px, self.py, self.pz]
 
   52     def __sub__(self, other):
 
   53         return FourMomentum(self.px-other.px, self.py-other.py, self.pz-other.pz, self.e-other.e)
 
   55     def __add__(self, other):
 
   56         return FourMomentum(self.px+other.px, self.py+other.py, self.pz+other.pz, self.e+other.e)
 
   59         return sqrt(self.px**2 + self.py**2 + self.pz**2)
 
   62     def __init__(self, pdg=0, p=FourMomentum(), status_code=0, start_vertex=0, end_vertex=0):
 
   64         self.status_code = status_code
 
   66         self.start_vertex_code = start_vertex
 
   67         self.end_vertex_code = end_vertex
 
   69     def start_vertex(self, event=None):
 
   70         return event.vertices[self.start_vertex_code] 
if event 
else None 
   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 
   76             return Vertex() 
if event 
else None 
   80     def __init__(self, pos=FourPosition(), parents=[], children=[]):
 
   82         self.parents = set([parent 
for parent 
in parents 
if parent > 0])
 
   83         self.children = set([child 
for child 
in children 
if child > 0])
 
   85     def add_parents(self, parents=[]):
 
   86         [self.parents.add(parent) 
for parent 
in parents 
if parent > 0]
 
   88     def add_children(self, children=[]):
 
   89         [self.children.add(child) 
for child 
in children 
if child > 0]
 
   91     def in_particles(self, event=None):
 
   93             return [event.particles[bar_code] 
for bar_code 
in self.parents]
 
   97     def out_particles(self, event=None):
 
   99             return [event.particles[bar_code] 
for bar_code 
in self.children]
 
  103     def distance(self, other=None):
 
  104         return self.pos.distance(other.pos) 
if other 
is not None else 0.
 
  107     def __init__(self, number = 0, process_id = 0, weights = []):
 
  109         self.weights = weights
 
  110         self.process_id = process_id
 
  111         self.units = [
None, 
None]
 
  112         self.cross_section = [
None, 
None]
 
  118     def __init__(self, filename):
 
  120         self._file = open(filename)
 
  124             status = self._read_hepmc_line()
 
  125             if status 
and self._line.startswith(
"HepMC::Version"):
 
  126                 self.version = self._line.split()[1]
 
  128         while status 
and not self._line.startswith(
"HepMC::IO_GenEvent-START_EVENT_LISTING"):
 
  129             self._read_hepmc_line()
 
  131     def _read_hepmc_line(self):
 
  132         self._line = self._file.readline()
 
  135         self._line = self._line.strip(
" \n")
 
  138     def read_event(self):
 
  139         if not self._line 
or self._line.startswith(
"HepMC::IO_GenEvent-END_EVENT_LISTING"):
 
  141         while self._line.startswith(
"HepMC"):
 
  142               self._read_hepmc_line()
 
  143         if not self._line.startswith(
"E "):
 
  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()
 
  153         for v_count 
in range(num_vertices):
 
  154             v_code, vertex, num_in_particles, num_out_particles = self._parse_vertex()
 
  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)
 
  170                             in_particles[out_v_code].append(p_code)
 
  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)
 
  180     def _parse_cross_section(self):
 
  181         tokens = self._line.split()
 
  182         return [float(x) 
for x 
in tokens[1:3]]
 
  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:]]
 
  189     def _parse_units(self):
 
  190         tokens = self._line.split()
 
  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])
 
  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