|
27 | 27 | import uuid |
28 | 28 |
|
29 | 29 | import numpy |
| 30 | +import xxhash |
30 | 31 |
|
31 | 32 | import uproot.compression |
32 | 33 | import uproot.const |
@@ -1730,58 +1731,62 @@ def add_tree( |
1730 | 1731 | def add_rntuple(self, sink, name, title, akform): |
1731 | 1732 | import uproot.writing._cascadentuple |
1732 | 1733 |
|
| 1734 | + rntuple_spec_version_epoch = 1 |
| 1735 | + rntuple_spec_version_major = 0 |
| 1736 | + rntuple_spec_version_minor = 0 |
| 1737 | + rntuple_spec_version_patch = 0 |
| 1738 | + |
1733 | 1739 | anchor = uproot.writing._cascadentuple.NTuple_Anchor( |
1734 | | - None, 0, 0, 48, None, None, None, None, None, None, 0 |
| 1740 | + None, |
| 1741 | + rntuple_spec_version_epoch, |
| 1742 | + rntuple_spec_version_major, |
| 1743 | + rntuple_spec_version_minor, |
| 1744 | + rntuple_spec_version_patch, |
| 1745 | + None, |
| 1746 | + None, |
| 1747 | + None, |
| 1748 | + None, |
| 1749 | + None, |
| 1750 | + None, |
| 1751 | + 0, # TODO: Fix this |
1735 | 1752 | ) |
1736 | 1753 |
|
1737 | 1754 | header = uproot.writing._cascadentuple.NTuple_Header(None, name, "", akform) |
1738 | 1755 |
|
1739 | 1756 | footer = uproot.writing._cascadentuple.NTuple_Footer( |
1740 | | - None, 0, header._crc32, akform |
| 1757 | + None, 0, header._checksum, akform |
1741 | 1758 | ) |
1742 | 1759 |
|
1743 | | - # the empty page list is hard-coded bytes which represents: |
1744 | | - # 0 1 2 3 |
1745 | | - # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
1746 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1747 | | - # | Envelope Version | Minimum Version | |
1748 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1749 | | - # | Size |T| |
1750 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1751 | | - # | Number of Items (for list frames) |Reserv.| |
1752 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1753 | | - # | FRAME PAYLOAD | |
1754 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1755 | | - # | CRC32 | |
1756 | | - # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1757 | | - # |
1758 | | - # - Envelope Version = 1 (0x0100) |
1759 | | - # - Minimum Version = 1 (0x0100) |
1760 | | - # - Size = -8 (0xf8ffffff) [value is negative because this is a list] |
1761 | | - # - Number of Items = 0 (0x00000000) [empty list] |
1762 | | - # - FRAME PAYLOAD = empty [because number of items is 0] |
1763 | | - # - CRC32 = 2678769841 |
1764 | | - # manually calculate CRC32: |
1765 | | - |
1766 | | - # In [1]: zlib.crc32(b'\x01\x00\x01\x00\xf8\xff\xff\xff\00\00\00\00') |
1767 | | - # Out[1]: 2678769841 |
1768 | | - # In [2]: np.array([177, 200, 170, 159], dtype=np.uint8).view("uint32") |
1769 | | - # Out[2]: array([2678769841], dtype=uint32) |
1770 | | - |
1771 | | - empty_page_list_bytes = numpy.array( |
1772 | | - [1, 0, 1, 0, 248, 255, 255, 255, 0, 0, 0, 0, 177, 200, 170, 159], |
1773 | | - dtype=numpy.uint8, |
| 1760 | + empty_page_list_headerbytes = ( |
| 1761 | + uproot.writing._cascadentuple._serialize_envelope_header( |
| 1762 | + uproot.const.RNTupleEnvelopeType.PAGELIST, 48 |
| 1763 | + ) |
1774 | 1764 | ) |
1775 | | - offset = self._freesegments.allocate(16) |
1776 | | - footer.cluster_group_record_frames[0].page_list_envlink.locator = ( |
1777 | | - uproot.writing._cascadentuple.NTuple_Locator(16, offset) |
| 1765 | + header.serialize() # so that checksum is computed |
| 1766 | + empty_page_list_payloadbytes = ( |
| 1767 | + uproot.models.RNTuple._rntuple_checksum_format.pack(header._checksum) |
| 1768 | + ) |
| 1769 | + empty_page_list_payloadbytes += ( |
| 1770 | + uproot.writing._cascadentuple._serialize_rntuple_list_frame([]) |
| 1771 | + ) # cluster summaries |
| 1772 | + empty_page_list_payloadbytes += ( |
| 1773 | + uproot.writing._cascadentuple._serialize_rntuple_list_frame([]) |
| 1774 | + ) # page locations |
| 1775 | + empty_page_list_bytes = ( |
| 1776 | + empty_page_list_headerbytes + empty_page_list_payloadbytes |
| 1777 | + ) |
| 1778 | + |
| 1779 | + empty_page_checksum = xxhash.xxh3_64_intdigest(empty_page_list_bytes) |
| 1780 | + checksum_bytes = uproot.models.RNTuple._rntuple_checksum_format.pack( |
| 1781 | + empty_page_checksum |
1778 | 1782 | ) |
| 1783 | + empty_page_list_bytes += checksum_bytes |
1779 | 1784 |
|
1780 | 1785 | ntuple = uproot.writing._cascadentuple.NTuple( |
1781 | 1786 | self, name, title, akform, self._freesegments, header, footer, [], anchor |
1782 | 1787 | ) |
1783 | 1788 |
|
1784 | | - sink.write(offset, empty_page_list_bytes) |
| 1789 | + # sink.write(offset, empty_page_list_bytes) |
1785 | 1790 | ntuple.write(sink) |
1786 | 1791 | sink.flush() |
1787 | 1792 | return ntuple |
|
0 commit comments