Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/rootfilespec/rntuple/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ class FieldDescription(RecordFrame):
- Bit: Meaning
- 0x01: Repetitive field, i.e. for every entry `n` copies of the field are stored
- 0x02: Projected field
- 0x04: Has ROOT type checksum as reported by TClass"""
- 0x04: Has ROOT type checksum as reported by TClass
- 0x08: The field is a collection that was stored using a SoA layout
(no effect on the on-disk representation; adds no optional field)"""
fFieldName: RString
"""The name of the field."""
fTypeName: RString
Expand Down Expand Up @@ -178,13 +180,15 @@ class ColumnDescription(RecordFrame):
- 0x02: Column with a range of possible values"""
fRepresentationIndex: Annotated[int, Fmt("<H")]
"""The index of the representation of the column in the list of representations for the field."""
# abbott TODO: verify the below are signed. make PR updating ROOT documentation if so (indicate signed bit in table)
fFirstElementIndex: Annotated[int | None, OptionalField("<q", "fFlags", "&", 0x01)]
"""The index of the first element in the column. Present only if flag 0x01 is set (deferred column)."""
fMinValue: Annotated[int | None, OptionalField("<q", "fFlags", "&", 0x02)]
"""The minimum value of the column. Present only if flag 0x02 is set (column with range of values)."""
fMaxValue: Annotated[int | None, OptionalField("<q", "fFlags", "&", 0x02)]
"""The maximum value of the column. Present only if flag 0x02 is set (column with range of values)."""
"""The index of the first element in the column. Present only if flag 0x01 is set (deferred column).
Signed: a negative value means the column is deferred and suppressed."""
fMinValue: Annotated[float | None, OptionalField("<d", "fFlags", "&", 0x02)]
"""The minimum value of the column, an IEEE 754 double.
Present only if flag 0x02 is set (column with range of values)."""
fMaxValue: Annotated[float | None, OptionalField("<d", "fFlags", "&", 0x02)]
"""The maximum value of the column, an IEEE 754 double.
Present only if flag 0x02 is set (column with range of values)."""


@serializable
Expand Down
34 changes: 34 additions & 0 deletions tests/test_column_value_range.py
Comment thread
nsmith- marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from skhep_testdata import data_path # type: ignore[import-not-found]

from rootfilespec.bootstrap import ROOT3a3aRNTuple
from rootfilespec.reader import open_path
from rootfilespec.rntuple.RNTuple import RNTuple
from rootfilespec.rntuple.schema import ColumnType


def test_column_value_range_is_double():
"""Issue #75: a column's value range is a pair of IEEE 754 doubles

The file's quantized columns (4 to 10, fields quant1 to quant32) all have
the range [-2.0, 3.0]. Read as int64, the same bytes are the bit patterns
-4611686018427387904 and 4613937818241073152.
"""
filename = "test_float_types_rntuple_v1-0-0-0.root"
with open_path(data_path(filename)) as reader:
anchor = reader.fetch(reader.keylist()["ntuple"])
assert isinstance(anchor, ROOT3a3aRNTuple)
rntuple = RNTuple.from_anchor(anchor, reader.fetch.buffer)
Comment thread
nsmith- marked this conversation as resolved.

columns = rntuple.schemaDescription.columnDescriptions
with_range = [i for i, c in enumerate(columns) if c.fFlags & 0x02]
assert with_range == list(range(4, 11))
for i in with_range:
column = columns[i]
assert column.fColumnType == ColumnType.kReal32Quant
assert column.fMinValue == -2.0
assert column.fMaxValue == 3.0
assert isinstance(column.fMinValue, float)
for i, column in enumerate(columns):
if i not in with_range:
assert column.fMinValue is None
assert column.fMaxValue is None
Loading