diff --git a/.gitignore b/.gitignore
index 1ee61124c19e2a83dd6f7cd6d86a8f919caa7509..80c82d0c089f097cabee124d463b4d71bf441720 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,4 +42,7 @@ doc/auto_examples/
 doc/modules/
 doc/api
 
+# 
+junit*.xml
+reports
 
diff --git a/jobcards/examples/example.job b/jobcards/examples/example.job
index f7935955e6f64b4d06239b8b9910f15f3364e5ae..9a36c16efe8e0d2dbf358fb73610dd5beb3f66c3 100644
--- a/jobcards/examples/example.job
+++ b/jobcards/examples/example.job
@@ -3,7 +3,7 @@
 	flavor_ID = 2 		! 1:electron, 2:muon, 3:tau
 	nuXsectionMode = 6 	! 6: dSigmaMC
 	includeDIS = .true. 	! enables DIS events
-	printAbsorptionXS = T
+	printAbsorptionXS = .true.
 /
 
 &target
@@ -44,7 +44,7 @@
 
 
 &neutrinoAnalysis
-	outputEvents = .true	! output list of events and
+	outputEvents = .true.	! output list of events and
 				! all outgoing particles in
 				! each event to the file 
 				! FinalEvents.dat
diff --git a/km3buu/output.py b/km3buu/output.py
index 4091de162483da87c6e3214c6eca3fff9c3629da..0fec0a94c54ebe2285c346be11359ea448212f7e 100644
--- a/km3buu/output.py
+++ b/km3buu/output.py
@@ -1,4 +1,4 @@
-# Filename: io.py
+# Filename: output.py
 """
 IO for km3buu
 
@@ -15,16 +15,54 @@ __status__ = "Development"
 import re
 import mmap
 import numpy as np
+import pylhe
 from io import StringIO
 from os import listdir
 from os.path import isfile, join, abspath
 from tempfile import TemporaryDirectory
+from collections import defaultdict
+import awkward1
+import itertools
 
 from .jobcard import Jobcard
 
 EVENT_FILENAME = "FinalEvents.dat"
 XSECTION_FILENAMES = {"all": "neutrino_absorption_cross_section_ALL.dat"}
 
+EVENT_FILE_DTYPE = np.dtype([
+    ("run", np.uint32),
+    ("event", np.uint32),
+    ("id", np.int32),
+    ("charge", np.float64),
+    ("perweight", np.float64),
+    ("x", np.float64),
+    ("y", np.float64),
+    ("z", np.float64),
+    ("p_t", np.float64),
+    ("p_x", np.float64),
+    ("p_y", np.float64),
+    ("p_z", np.float64),
+    ("history", np.int32),
+    ("pID", np.int32),
+    ("nu_energy", np.float64),
+    ("Bx", np.float64),
+    ("By", np.float64),
+])
+
+LHE_NU_INFO_DTYPE = np.dtype([('type', np.int), ('weight', np.float64),
+                              ('mom_lepton_in_E', np.float64),
+                              ('mom_lepton_in_x', np.float64),
+                              ('mom_lepton_in_y', np.float64),
+                              ('mom_lepton_in_z', np.float64),
+                              ('mom_lepton_out_E', np.float64),
+                              ('mom_lepton_out_x', np.float64),
+                              ('mom_lepton_out_y', np.float64),
+                              ('mom_lepton_out_z', np.float64),
+                              ('mom_nucleon_in_E', np.float64),
+                              ('mom_nucleon_in_x', np.float64),
+                              ('mom_nucleon_in_y', np.float64),
+                              ('mom_nucleon_in_z', np.float64)])
+
 
 def read_nu_abs_xsection(filepath):
     """
@@ -39,14 +77,32 @@ def read_nu_abs_xsection(filepath):
     """
     with open(filepath, "r") as f:
         lines = f.readlines()
-    header = re.sub(r'\d+:|#', '', lines[0]).split()
+    header = re.sub(r"\d+:|#", "", lines[0]).split()
     dt = np.dtype([(field, np.float64) for field in header])
     values = np.genfromtxt(StringIO(lines[-1]), dtype=dt)
     return values
 
 
+def parse_gibuu_event_info(line):
+    fields = line.split()[1:]
+    if int(fields[0]) != 5:
+        raise NotImplementedError(
+            "Event information type %s cannot be parsed yet!" % fields[0])
+    else:
+        return np.genfromtxt(StringIO(line[3:]), dtype=LHE_NU_INFO_DTYPE)
+
+
 class FinalEvents:
+    """ 
+    Reader for FinalEvents.dat
+
+    Parameters
+    ----------
+    filepath: str
+        Filepath pointing to the FinalEvents file
+    """
     def __init__(self, filepath):
+        """ Constructor """
         self._filepath = filepath
         with open(self._filepath, "r") as f:
             self._final_events_map = mmap.mmap(f.fileno(),
@@ -58,7 +114,7 @@ class FinalEvents:
         self._final_events_map.seek(0)
         line_pos = []
         while True:
-            next_pos = self._final_events_map.find(b'\n') + 1
+            next_pos = self._final_events_map.find(b"\n") + 1
             if next_pos == 0:
                 break
             line_pos.append(next_pos)
@@ -73,28 +129,19 @@ class FinalEvents:
         s = []
         for p in pos:
             self._final_events_map.seek(p)
-            line = self._final_events_map.readline().decode('utf-8').strip(
+            line = self._final_events_map.readline().decode("utf-8").strip(
                 "\n")
-            s.append("%s %.3f %3f\n" % (line, 0., 0.))
-        dt = np.dtype([('run', np.uint32), ('event', np.uint32),
-                       ('id', np.int32), ('charge', np.float64),
-                       ('perweight', np.float64), ('x', np.float64),
-                       ('y', np.float64), ('z', np.float64),
-                       ('p_t', np.float64), ('p_x', np.float64),
-                       ('p_y', np.float64), ('p_z', np.float64),
-                       ('history', np.int32), ('pID', np.int32),
-                       ('nu_energy', np.float64), ('Bx', np.float64),
-                       ('By', np.float64)])
-        values = np.genfromtxt(StringIO('\n'.join(s)), dtype=dt)
+            s.append("%s %.3f %3f\n" % (line, 0.0, 0.0))
+        values = np.genfromtxt(StringIO("\n".join(s)), dtype=EVENT_FILE_DTYPE)
         # values['Bx'] = / 2. /
-        values['By'] = 1 - values["p_t"] / values["nu_energy"]
+        values["By"] = 1 - values["p_t"] / values["nu_energy"]
         return values
 
     def __len__(self):
         return len(self._line_pos)
 
 
-OUTPUT_FILE_WRAPPERS = {'FinalEvents.dat': FinalEvents}
+OUTPUT_FILE_WRAPPERS = {"FinalEvents.dat": FinalEvents}
 
 
 class GiBUUOutput:
@@ -120,9 +167,11 @@ class GiBUUOutput:
                     FinalEvents(join(self._data_path, EVENT_FILENAME)))
         if XSECTION_FILENAMES["all"] in self.output_files:
             setattr(
-                self, "xsection",
+                self,
+                "xsection",
                 read_nu_abs_xsection(
-                    join(self._data_path, XSECTION_FILENAMES["all"])))
+                    join(self._data_path, XSECTION_FILENAMES["all"])),
+            )
         self._jobcard = None
 
     def associate_jobcard(self, jobcard):
diff --git a/requirements.txt b/requirements.txt
index 3cdbd3a9373e7b26e3127f4625905d065fe76a78..c61ed021bd4029704f9aa0eb20e830ee66b39086 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ thepipe
 particle
 click
 pylhe
+f90nml
diff --git a/setup.py b/setup.py
index 0d4749bb0af2eb8085283fa30be58a82033176bb..e7c6f7346c1fc9555b83fbf9a46ebe3d6f4c19e4 100644
--- a/setup.py
+++ b/setup.py
@@ -36,10 +36,9 @@ setup(
         'tag_regex': r'^(?P<prefix>v)?(?P<version>[^\+]+)(?P<suffix>.*)?$',
     },
     install_requires=REQUIREMENTS,
-    extras_require={
-        'dev': DEV_REQUIREMENTS
-        },
+    extras_require={'dev': DEV_REQUIREMENTS},
     python_requires='>=3.0',
+    entry_points={'console_scripts': ['km3buu=km3buu.cmd:main']},
     classifiers=[
         'Development Status :: 3 - Alpha',
         'Intended Audience :: Developers',