Repository navigation
fix: write RNTuple data whose lists are all empty - #1812
Conversation
A list with only empty entries has Awkward type 'var * unknown'. Extending an RNTuple with such a chunk was rejected as incompatible, and creating one from it hit an AssertionError. Fill unknown parts of the data with the type the RNTuple expects, and write a schema that is unknown as float64, as the TTree writer does.
Codecov Report❌ Patch coverage is
Additional details and impacted files
|
|
🤖 AI text below 🤖 Thanks for this! I think creating an RNTuple and extending one need different handling here. Creation: raise instead of guessing file.mkrntuple("ntuple", {"muons": "var * float64"})So the Extend: keep filling from the schema, but simplify. In
It's also another walk over layout types that has to be kept in sync with A related case: a zero-length chunk with unknown type ( |
…n extend Review feedback: - Creating an RNTuple from data with Awkward's unknown type now raises a TypeError pointing to mkrntuple with an explicit type, instead of guessing float64 as the permanent schema. - extend fills unknown types with ak.enforce_type against the stored schema, after the tuple-field conversion, and only when the chunk has an unknown type. This replaces the hand-written layout walk. - Before enforce_type, the chunk's form must match the schema everywhere except at unknown types, so enforce_type can't silently convert other values (e.g. 1.5 to 1 in an int64 field). - A zero-length chunk with unknown type (ak.Array([])) now adds an empty cluster, as a zero-length chunk with a known type does.
|
Thanks @ariostas, that split makes sense. c92b913 does it that way:
Two things came up along the way:
Locally the full suite passes (1186 passed, 303 skipped), and 4 of the 5 new tests fail on main. The macOS CI failures on this run look unrelated to me (the Pyodide and ROOT jobs failed at plugin loading), but I can't see the macOS logs anymore. Could you re-run them? Separately, while testing I noticed that extending an RNTuple with a union field re-reads the first chunk, on main too: f["n"] = {"u": ak.Array([[1, 2], 3.5])}
f["n"].extend({"u": ak.Array([[5], 4.5])})
# reads back [[1, 2], 3.5, [1, 2], 3.5]Happy to open a separate issue for that if you'd like. |
|
Ah, never mind about the union issue. I see you already opened #1815 for it. |
|
I merged |
Extending an RNTuple with lists that are all empty now works, and test_1812 checks it, including that other mismatched types still fail. Assisted-by: Claude Code:claude-opus-5-5
Extending an RNTuple with lists that are all empty now works, and test_1812 checks it, including that other mismatched types still fail. Assisted-by: Claude Code:claude-opus-5-5
scikit-hep#1812 merged after the coverage PRs were split, and two of the ways a chunk with unknown types can mismatch the schema weren't tested: a field of a different kind, and a record with different fields. Assisted-by: Claude Code:claude-opus-5-5
When writing in chunks, a chunk where every entry of a jagged field is empty has Awkward type
var * unknown. RNTuple writing fails on it, but the TTree writer accepts it:The same chunks work with
mktree+extend. The TTree writer turns the unknown type intofloat64(_branch_ak_to_np).Changes in
writing/_cascadentuple.py:extendnow calls a new_fill_unknown. It walks the data next to the RNTuple's form and replaces eachEmptyArraywith a zero-length array of the type the form expects at that position (form.length_zero_array()). Nothing else in the data is converted, so data with a different type, such as floats into anint64field, is still rejected by the existing check._to_packed_formwrites anEmptyFormasfloat64, matching the TTree writer, so an RNTuple can also be created from such a chunk.tests/test_1812_rntuple_unknown_type_empty_lists.py(named after the expected PR number; I'll rename it if this gets a different one) covers:The two new-behaviour tests fail on
mainand pass with this change. The full test suite passes locally (-m "not network and not xrootd and not distributed": 1170 passed, 253 skipped), and black and ruff at the pre-commit versions are clean.AI-assisted (Claude). I reviewed the code and ran the tests.