From 9effd6755b3dd9e251a72d6e4df62d1fa4fcf0ae Mon Sep 17 00:00:00 2001
From: Tamas Gal <tgal@km3net.de>
Date: Tue, 19 Nov 2019 01:47:08 +0100
Subject: [PATCH] Preliminary reading of timeslice frames

---
 km3io/jpp.py      | 47 ++++++++++++++++++++++++++++++++++++++++-------
 tests/test_jpp.py | 14 +++++++++-----
 2 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/km3io/jpp.py b/km3io/jpp.py
index eb5feec..7540c61 100644
--- a/km3io/jpp.py
+++ b/km3io/jpp.py
@@ -49,8 +49,9 @@ class JppTimeslices:
     def _read_default_stream(self):
         """Read the default KM3NET_TIMESLICE stream"""
         tree = self.fobj[b'KM3NET_TIMESLICE'][b'KM3NET_TIMESLICE']
-        header = tree[b'KM3NETDAQ::JDAQTimesliceHeader']
-        self._timeslices['default'] = JppTimeslice(header)
+        headers = tree[b'KM3NETDAQ::JDAQTimesliceHeader']
+        superframes = tree[b'vector<KM3NETDAQ::JDAQSuperFrame>']
+        self._timeslices['default'] = (headers, superframes)
 
     def _read_streams(self):
         """Read the L0, L1, L2 and SN streams if available"""
@@ -61,13 +62,18 @@ class JppTimeslices:
         for stream in streams:
             tree = self.fobj[b'KM3NET_TIMESLICE_' +
                              stream][b'KM3NETDAQ::JDAQTimeslice']
-            header = tree[b'KM3NETDAQ::JDAQTimesliceHeader'][
+            headers = tree[b'KM3NETDAQ::JDAQTimesliceHeader'][
                 b'KM3NETDAQ::JDAQHeader'][b'KM3NETDAQ::JDAQChronometer']
-            self._timeslices[stream.decode("ascii")] = JppTimeslice(header)
+            superframes = tree[b'vector<KM3NETDAQ::JDAQSuperFrame>']
+            self._timeslices[stream.decode("ascii")] = (headers, superframes)
+
+    def stream(self, stream, idx):
+        ts = self._timeslices[stream]
+        return JppTimeslice(ts[0], ts[1], idx)
 
     def __str__(self):
-        return "Available timeslice streams: {}".format(','.join(
-            s.decode("ascii") for s in self._timeslices.keys()))
+        return "Available timeslice streams: {}".format(', '.join(
+            s for s in self._timeslices.keys()))
 
     def __repr__(self):
         return str(self)
@@ -75,8 +81,35 @@ class JppTimeslices:
 
 class JppTimeslice:
     """A wrapper for a Jpp timeslice"""
-    def __init__(self, header):
+    def __init__(self, header, superframe, idx):
         self.header = header
+        self._frames = {}
+        self._superframe = superframe
+        self._idx = idx
+
+    @property
+    def frames(self):
+        if not self._frames:
+            self._read_frames()
+        return self._frames
+
+    def _read_frames(self):
+        """Populate a dictionary of frames with the module ID as key"""
+        hits_buffer = self._superframe[
+            b'vector<KM3NETDAQ::JDAQSuperFrame>.buffer'].array(
+                uproot.asjagged(uproot.astable(
+                    uproot.asdtype([("pmt", "u1"), ("tdc", "u4"),
+                                    ("tot", "u1")])),
+                                skipbytes=6))[self._idx]
+        n_hits = self._superframe[
+            b'vector<KM3NETDAQ::JDAQSuperFrame>.numberOfHits'].array()[
+                self._idx]
+        module_ids = self._superframe[
+            b'vector<KM3NETDAQ::JDAQSuperFrame>.id'].array()[self._idx]
+        idx = 0
+        for module_id, n_hits in zip(module_ids, n_hits):
+            self._frames[module_id] = hits_buffer[idx:idx + n_hits]
+            idx += n_hits
 
     def __str__(self):
         return "Jpp timeslice"
diff --git a/tests/test_jpp.py b/tests/test_jpp.py
index e24bc94..4b235f9 100644
--- a/tests/test_jpp.py
+++ b/tests/test_jpp.py
@@ -120,9 +120,13 @@ class TestTimeslices(unittest.TestCase):
     def setUp(self):
         self.ts = JppReader(os.path.join(SAMPLES_DIR,
                                          "jpp_v12.0.0.root")).timeslices
+
     def test_data_lengths(self):
-        assert 3 == len(self.ts._timeslices["default"].header)
-        assert 0 == len(self.ts._timeslices["L0"].header)
-        assert 3 == len(self.ts._timeslices["L1"].header)
-        assert 0 == len(self.ts._timeslices["L2"].header)
-        assert 3 == len(self.ts._timeslices["SN"].header)
+        assert 3 == len(self.ts._timeslices["default"][0])
+        assert 0 == len(self.ts._timeslices["L0"][0])
+        assert 3 == len(self.ts._timeslices["L1"][0])
+        assert 0 == len(self.ts._timeslices["L2"][0])
+        assert 3 == len(self.ts._timeslices["SN"][0])
+
+    def test_reading_frames(self):
+        assert 8 == len(self.ts.stream("SN", 1).frames[808447186])
-- 
GitLab