From 3e3e7165438cf9287c37bfb289a28f776aa490c5 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Fri, 30 Aug 2024 10:31:39 +0200 Subject: [PATCH 01/14] add test for known forth of 2D vector ElementLinks --- tests/test_xxxx_add_known_forth_for_atlas.py | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/test_xxxx_add_known_forth_for_atlas.py diff --git a/tests/test_xxxx_add_known_forth_for_atlas.py b/tests/test_xxxx_add_known_forth_for_atlas.py new file mode 100644 index 000000000..f73a3531c --- /dev/null +++ b/tests/test_xxxx_add_known_forth_for_atlas.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +import awkward +import skhep_testdata +import uproot + +VECTOR_VECTOR_ELEMENTLINK_BRANCHES = [ + "AnalysisHLT_e12_lhloose_nod0_2mu10AuxDyn.TrigMatchedObjects", + "AnalysisElectronsAuxDyn.caloClusterLinks", + "AnalysisPhotonsAuxDyn.vertexLinks", + "TruthMuonsAuxDyn.childLinks", + "AnalysisElectronsAuxDyn.trackParticleLinks", + "PrimaryVerticesAuxDyn.neutralParticleLinks", + "AnalysisTauJetsAuxDyn.tauTrackLinks", +] + + +def test_pickup_vector_vector_elementlink(): + with uproot.open( + {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} + ) as tree: + for key in VECTOR_VECTOR_ELEMENTLINK_BRANCHES: + branch = tree[key] + assert branch.interpretation._complete_forth_code is not None + assert branch.interpretation._form is not None + + +def test_consistent_library_np_vector_vector_elementlink(): + arrays_np = {} + with uproot.open( + {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} + ) as tree: + for key in VECTOR_VECTOR_ELEMENTLINK_BRANCHES: + arrays_np[key] = tree[key].array(library="np") + arrays_ak = {} + with uproot.open( + {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} + ) as tree: + for key in VECTOR_VECTOR_ELEMENTLINK_BRANCHES: + arrays_ak[key] = tree[key].array() + for key in arrays_np: + array_ak = arrays_ak[key] + array_np = uproot.interpretation.library._object_to_awkward_array(awkward, array_ak.layout.form.to_dict(), arrays_np[key]) + for field in array_ak.fields: + assert awkward.all(array_np[field] == array_ak[field]) From d4acbdc877ad5a86317a498edd976df0bf330555 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Fri, 30 Aug 2024 10:44:22 +0200 Subject: [PATCH 02/14] add known forth for 2D vector ElementLinks --- .../interpretation/known_forth/__init__.py | 21 +++++++ .../known_forth/atlas/__init__.py | 5 ++ .../known_forth/atlas/element_link.py | 57 +++++++++++++++++++ src/uproot/interpretation/objects.py | 13 ++++- 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/uproot/interpretation/known_forth/__init__.py create mode 100644 src/uproot/interpretation/known_forth/atlas/__init__.py create mode 100644 src/uproot/interpretation/known_forth/atlas/element_link.py diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py new file mode 100644 index 000000000..afb9d0d88 --- /dev/null +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -0,0 +1,21 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE + +""" +This module defines known forth code for types it is known a priori. +""" +from __future__ import annotations + + +def known_forth_of(branch): + from uproot.interpretation.known_forth.atlas.element_link import ( + vector_vector_element_link, + ) + + if ( + # len(branch.branches) == 0 # don't understand why this goes nuts + # and branch.has_member("fClassName") + branch.has_member("fClassName") + ): + typename = branch.member("fClassName").replace(" ", "") + if typename.startswith("vector stack + stream seek + 6 stream skip + stream !I-> stack + dup node1-offsets +<- stack + 0 do + stream !I-> stack + dup node2-offsets +<- stack + 0 do + 20 stream skip + stream !I-> node3-data + stream !I-> node4-data + loop + loop +loop +""", + ListOffsetForm( + "i64", + ListOffsetForm( + "i64", + RecordForm( + [ + NumpyForm("uint32", form_key="node3"), + NumpyForm("uint32", form_key="node4"), + ], + ["m_persKey", "m_persIndex"], + ), + form_key="node2", + ), + form_key="node1", + ), +) diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 8404977db..401de020d 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -28,6 +28,7 @@ import uproot import uproot._awkwardforth +from uproot.interpretation.known_forth import known_forth_of class AsObjects(uproot.interpretation.Interpretation): @@ -45,14 +46,20 @@ class AsObjects(uproot.interpretation.Interpretation): :ref:`uproot.interpretation.objects.AsObjects.simplify` attempts to replace this interpretation with a faster-to-read equivalent, but not all data types can be simplified. + + # TODO: known_forth can define forth code and forms for special cases that will be picked up here as well """ def __init__(self, model, branch=None): self._model = model self._branch = branch - self._form = None self._forth = True - self._complete_forth_code = None + known_forth = known_forth_of(branch) + if known_forth is not None: + self._complete_forth_code, self._form = known_forth + else: + self._complete_forth_code = None + self._form = None self._forth_lock = threading.Lock() @property @@ -122,6 +129,8 @@ def awkward_form( tobject_header=False, breadcrumbs=(), ): + if self._form is not None: # TODO: is this really fine? + return self._form context = self._make_context( context, index_format, header, tobject_header, breadcrumbs ) From d27cc71729af9deb20af41ff8e0cd1575b843fb5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:57:27 +0000 Subject: [PATCH 03/14] style: pre-commit fixes --- tests/test_xxxx_add_known_forth_for_atlas.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_xxxx_add_known_forth_for_atlas.py b/tests/test_xxxx_add_known_forth_for_atlas.py index f73a3531c..6519a172c 100644 --- a/tests/test_xxxx_add_known_forth_for_atlas.py +++ b/tests/test_xxxx_add_known_forth_for_atlas.py @@ -40,6 +40,8 @@ def test_consistent_library_np_vector_vector_elementlink(): arrays_ak[key] = tree[key].array() for key in arrays_np: array_ak = arrays_ak[key] - array_np = uproot.interpretation.library._object_to_awkward_array(awkward, array_ak.layout.form.to_dict(), arrays_np[key]) + array_np = uproot.interpretation.library._object_to_awkward_array( + awkward, array_ak.layout.form.to_dict(), arrays_np[key] + ) for field in array_ak.fields: assert awkward.all(array_np[field] == array_ak[field]) From 5a0456cc4008cf29df984eecb8a76dee86c8a212 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Fri, 30 Aug 2024 13:45:24 +0200 Subject: [PATCH 04/14] rename test file --- ..._forth_for_atlas.py => test_1282_add_known_forth_for_atlas.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_xxxx_add_known_forth_for_atlas.py => test_1282_add_known_forth_for_atlas.py} (100%) diff --git a/tests/test_xxxx_add_known_forth_for_atlas.py b/tests/test_1282_add_known_forth_for_atlas.py similarity index 100% rename from tests/test_xxxx_add_known_forth_for_atlas.py rename to tests/test_1282_add_known_forth_for_atlas.py From d23c71193a9b596b48bcf9e599cdca785e0a9585 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Mon, 2 Sep 2024 10:34:02 +0200 Subject: [PATCH 05/14] update form instead of replacing (fixes tests for assumed forms) --- .../interpretation/known_forth/__init__.py | 6 +--- .../known_forth/atlas/element_link.py | 26 ++++++---------- src/uproot/interpretation/objects.py | 30 +++++++++++++++++-- tests/test_1282_add_known_forth_for_atlas.py | 13 ++++---- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index afb9d0d88..98ab853de 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -11,11 +11,7 @@ def known_forth_of(branch): vector_vector_element_link, ) - if ( - # len(branch.branches) == 0 # don't understand why this goes nuts - # and branch.has_member("fClassName") - branch.has_member("fClassName") - ): + if branch.has_member("fClassName"): typename = branch.member("fClassName").replace(" ", "") if typename.startswith("vector Date: Mon, 2 Sep 2024 11:01:42 +0200 Subject: [PATCH 06/14] add treatment for branch=None in known_forth discovery --- src/uproot/interpretation/known_forth/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index 98ab853de..498d51621 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -11,6 +11,9 @@ def known_forth_of(branch): vector_vector_element_link, ) + if branch is None: + return + if branch.has_member("fClassName"): typename = branch.member("fClassName").replace(" ", "") if typename.startswith("vector Date: Mon, 16 Sep 2024 18:06:33 +0200 Subject: [PATCH 07/14] switch to hardcoded dict of typenames --- .../interpretation/known_forth/__init__.py | 27 ++++++--- .../known_forth/atlas/element_link.py | 57 +++++++++++++++---- src/uproot/interpretation/objects.py | 26 +-------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index 498d51621..895bc7dac 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -5,16 +5,25 @@ """ from __future__ import annotations +from uproot.interpretation.known_forth.atlas.element_link import VectorVectorElementLink -def known_forth_of(branch): - from uproot.interpretation.known_forth.atlas.element_link import ( - vector_vector_element_link, - ) +KNOWN_FORTH_DICT = { + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, +} - if branch is None: + +def known_forth_of(model): + if not hasattr(model, "typename"): + return + + typename = model.typename + + if typename not in KNOWN_FORTH_DICT: return - if branch.has_member("fClassName"): - typename = branch.member("fClassName").replace(" ", "") - if typename.startswith("vector>", r"\1", self.typename + ) + + @property + def awkward_form(self): + return { + "class": "ListOffsetArray", + "offsets": "i64", + "form_key": "node1", "content": { - "contents": [{"form_key": "node3"}, {"form_key": "node4"}], + "class": "ListOffsetArray", + "offsets": "i64", + "form_key": "node2", + "content": { + "class": "RecordArray", + "fields": ["m_persKey", "m_persIndex"], + "contents": [ + { + "class": "NumpyArray", + "primitive": "uint32", + "inner_shape": [], + "parameters": {}, + "form_key": "node3", + }, + { + "class": "NumpyArray", + "primitive": "uint32", + "inner_shape": [], + "parameters": {}, + "form_key": "node4", + }, + ], + "parameters": {"__record__": f"{self.inner_typename}"}, + }, }, - }, - }, -) + } diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 852ba3038..7d4acaa92 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -21,7 +21,6 @@ from __future__ import annotations import contextlib -import copy import json import threading @@ -33,23 +32,6 @@ from uproot.interpretation.known_forth import known_forth_of -def _updated_form(form, update_dict): - form = copy.deepcopy(form) - - def update(form, update_dict): - for key, value in update_dict.items(): - if isinstance(value, dict): - update(form[key], update_dict[key]) - elif isinstance(value, list): - for subform, subupdate in zip(form[key], update_dict[key]): - update(subform, subupdate) - else: - form[key] = value - - update(form, update_dict) - return form - - class AsObjects(uproot.interpretation.Interpretation): """ Args: @@ -74,12 +56,10 @@ def __init__(self, model, branch=None): self._branch = branch self._forth = True self._form = None - known_forth = known_forth_of(branch) + known_forth = known_forth_of(self._model) if known_forth is not None: - self._complete_forth_code, update_dict = known_forth - self._form = awkward.forms.from_dict( - _updated_form(self.awkward_form(branch.file).to_dict(), update_dict) - ) + self._complete_forth_code = known_forth.forth_code + self._form = known_forth.awkward_form else: self._complete_forth_code = None self._forth_lock = threading.Lock() From f2246b76cb31dc980b8d7834685929c15755d615 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Mon, 16 Sep 2024 18:09:44 +0200 Subject: [PATCH 08/14] delay awkward import --- src/uproot/interpretation/objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 7d4acaa92..242e31bb9 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -24,7 +24,6 @@ import json import threading -import awkward # TODO: delay import numpy import uproot @@ -131,6 +130,7 @@ def awkward_form( tobject_header=False, breadcrumbs=(), ): + awkward = uproot.extras.awkward() if self._form is not None: # TODO: is this really fine? if isinstance(self._form, dict): # TODO don't know when and why the form sometimes is a dict From eb3b97032a0fb60212c67a6d254a6466d0e49252 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Mon, 16 Sep 2024 18:32:23 +0200 Subject: [PATCH 09/14] make PrimaryVerticesAuxDyn.neutralParticleLinks work --- src/uproot/interpretation/known_forth/__init__.py | 1 + tests/test_1282_add_known_forth_for_atlas.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index 895bc7dac..9019cc192 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -14,6 +14,7 @@ "std::vector>>>": VectorVectorElementLink, "std::vector>>>": VectorVectorElementLink, "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, } diff --git a/tests/test_1282_add_known_forth_for_atlas.py b/tests/test_1282_add_known_forth_for_atlas.py index 17aa78b24..e57bcc26d 100644 --- a/tests/test_1282_add_known_forth_for_atlas.py +++ b/tests/test_1282_add_known_forth_for_atlas.py @@ -11,7 +11,7 @@ "AnalysisPhotonsAuxDyn.vertexLinks", "TruthMuonsAuxDyn.childLinks", "AnalysisElectronsAuxDyn.trackParticleLinks", - # "PrimaryVerticesAuxDyn.neutralParticleLinks", # TODO: currently fails because of `CannotBeAwkward` - see if we can circumvent this by providing the form + "PrimaryVerticesAuxDyn.neutralParticleLinks", "AnalysisTauJetsAuxDyn.tauTrackLinks", ] From 3c3ca6f8da80e93945385e07a3240dc1d9c512b4 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Tue, 17 Sep 2024 08:24:25 +0200 Subject: [PATCH 10/14] make if-statement for known_forth and awkward_form more clear Co-authored-by: Jim Pivarski --- src/uproot/interpretation/objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 242e31bb9..287bcc0ac 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -54,13 +54,13 @@ def __init__(self, model, branch=None): self._model = model self._branch = branch self._forth = True - self._form = None known_forth = known_forth_of(self._model) if known_forth is not None: self._complete_forth_code = known_forth.forth_code self._form = known_forth.awkward_form else: self._complete_forth_code = None + self._form = None self._forth_lock = threading.Lock() @property From 3b26ac477f9cdadf6369e7567d7b607053b2cda8 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Tue, 17 Sep 2024 08:26:53 +0200 Subject: [PATCH 11/14] add xAOD::MuonSegment_v1 to dict of known_forth with VectorVectorElementLink and sort keys --- src/uproot/interpretation/known_forth/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index 9019cc192..b3b0a5ae9 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -9,12 +9,13 @@ KNOWN_FORTH_DICT = { "std::vector>>>": VectorVectorElementLink, - "std::vector>>>": VectorVectorElementLink, - "std::vector>>>": VectorVectorElementLink, - "std::vector>>>": VectorVectorElementLink, - "std::vector>>>": VectorVectorElementLink, "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, + "std::vector>>>": VectorVectorElementLink, } From 7701596b2033887bfb62c62e4ef022aabff3eea8 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Tue, 17 Sep 2024 09:23:37 +0200 Subject: [PATCH 12/14] always convert self._form from dict in AsObjects.awkward_form --- src/uproot/interpretation/objects.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 287bcc0ac..7db93886a 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -130,13 +130,10 @@ def awkward_form( tobject_header=False, breadcrumbs=(), ): - awkward = uproot.extras.awkward() - if self._form is not None: # TODO: is this really fine? - if isinstance(self._form, dict): - # TODO don't know when and why the form sometimes is a dict - # (and if it causes problems to convert it here) - self._form = awkward.forms.from_dict(self._form) - return self._form + if self._form is not None: + awkward = uproot.extras.awkward() + return awkward.forms.from_dict(self._form) + context = self._make_context( context, index_format, header, tobject_header, breadcrumbs ) From 350f71e48d40fabb0c549477fce88dfa50804549 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Tue, 17 Sep 2024 12:27:57 +0200 Subject: [PATCH 13/14] treat more cases for typename --- .../interpretation/known_forth/__init__.py | 19 +++++++++++++++---- src/uproot/interpretation/objects.py | 3 ++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index b3b0a5ae9..35638b53b 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -5,6 +5,7 @@ """ from __future__ import annotations +import uproot from uproot.interpretation.known_forth.atlas.element_link import VectorVectorElementLink KNOWN_FORTH_DICT = { @@ -20,10 +21,20 @@ def known_forth_of(model): - if not hasattr(model, "typename"): - return - - typename = model.typename + """ + Args: + model: The :doc:`uproot.model.Model` to look up known forth for + + Returns an object with attributes `forth_code` and `awkward_form` if a known + special case exists, else None + """ + try: + typename = model.typename + except AttributeError: + try: + typename = model.classname + except AttributeError: + typename = uproot.model.classname_decode(model.__name__) if typename not in KNOWN_FORTH_DICT: return diff --git a/src/uproot/interpretation/objects.py b/src/uproot/interpretation/objects.py index 7db93886a..37306a135 100644 --- a/src/uproot/interpretation/objects.py +++ b/src/uproot/interpretation/objects.py @@ -47,7 +47,8 @@ class AsObjects(uproot.interpretation.Interpretation): replace this interpretation with a faster-to-read equivalent, but not all data types can be simplified. - # TODO: known_forth can define forth code and forms for special cases that will be picked up here as well + :doc:`uproot.interpretation.known_forth` defines forth code and forms for + special cases that will be picked up here as well """ def __init__(self, model, branch=None): From 13c7ffe1aa29efcd9a20ad75e858e46cd9b01b70 Mon Sep 17 00:00:00 2001 From: Nikolai Hartmann Date: Tue, 17 Sep 2024 12:58:02 +0200 Subject: [PATCH 14/14] flatten directory structure and add docstring for VectorVectorElementLink --- .../interpretation/known_forth/__init__.py | 8 ++++++-- .../{atlas/element_link.py => atlas.py} | 19 ++++++++++++++++++- .../known_forth/atlas/__init__.py | 5 ----- 3 files changed, 24 insertions(+), 8 deletions(-) rename src/uproot/interpretation/known_forth/{atlas/element_link.py => atlas.py} (72%) delete mode 100644 src/uproot/interpretation/known_forth/atlas/__init__.py diff --git a/src/uproot/interpretation/known_forth/__init__.py b/src/uproot/interpretation/known_forth/__init__.py index 35638b53b..0f0626e62 100644 --- a/src/uproot/interpretation/known_forth/__init__.py +++ b/src/uproot/interpretation/known_forth/__init__.py @@ -1,12 +1,16 @@ # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE """ -This module defines known forth code for types it is known a priori. +This module provides known forth code and awkward forms for types where it is known a priori. + +See :doc:`uproot.interpretation.known_forth.known_forth_of` for the function +that provides the lookup of known forth codes and :doc:`uproot.interpretation.known_forth.atlas.VectorVectorElementLink` for an +implementation used in ATLAS (D)AODs. """ from __future__ import annotations import uproot -from uproot.interpretation.known_forth.atlas.element_link import VectorVectorElementLink +from uproot.interpretation.known_forth.atlas import VectorVectorElementLink KNOWN_FORTH_DICT = { "std::vector>>>": VectorVectorElementLink, diff --git a/src/uproot/interpretation/known_forth/atlas/element_link.py b/src/uproot/interpretation/known_forth/atlas.py similarity index 72% rename from src/uproot/interpretation/known_forth/atlas/element_link.py rename to src/uproot/interpretation/known_forth/atlas.py index 04b766ba9..4db699748 100644 --- a/src/uproot/interpretation/known_forth/atlas/element_link.py +++ b/src/uproot/interpretation/known_forth/atlas.py @@ -1,7 +1,7 @@ # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE """ -This module defines known forth code for some ElementLink data types in ATLAS (D)AODs +This module defines ATLAS specific known forth code """ from __future__ import annotations @@ -10,6 +10,23 @@ class VectorVectorElementLink: + """ + Known forth and awkward form for ``std::vector>`` types in ATLAS (D)AODs + + The forth code was adjusted from what was provided in + ``branch._complete_forth_code`` after running ``.array()`` once. + + The binary data of one vector> looks as follows: + + * 6 bytes header for the outer vector + * 4 bytes big endian uint for the size of the outer vector (node1) + * for each outer vector element: + * 4 bytes big endian uint for the size of the inner vector (node2) + * for each inner vector element: + * 20 bytes header for the ElementLink object + * 4 bytes big endian uint for the ``m_persKey`` member (node3) + * 4 bytes big endian uint for the ``m_persIndex`` member (node4) + """ forth_code = """ input stream diff --git a/src/uproot/interpretation/known_forth/atlas/__init__.py b/src/uproot/interpretation/known_forth/atlas/__init__.py deleted file mode 100644 index 22f85a5db..000000000 --- a/src/uproot/interpretation/known_forth/atlas/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE - -""" -This module defines ATLAS specific known forth code -"""