uproot.writing.writable.WritableNTuple

Defined in uproot.writing.writable on line 2894.

class uproot.writing.writable.WritableNTuple(path, file, cascading)
Parameters:
  • path (tuple of str) – Path of directory names to this RNTuple.

  • file (uproot.WritableFile) – Handle to the file in which this RNTuple can be found.

  • cascading (uproot.writing._cascadentuple.NTuple) – The low-level directory object.

Represents a writable RNTuple from a ROOT file.

Assigning data to a directory creates an RNTuple object by default starting in Uproot v5.7.0. This creates the RNTuple object with all of its metadata and fills it with the contents of the arrays in one step. To separate the process of creating the RNTuple metadata from filling the first cluster, use the uproot.writing.writable.WritableDirectory.mkrntuple method:

my_directory.mkrntuple("tuple6", {"branch1": numpy_dtype, "branch2": awkward_type})

The numpy_dtype is any data that NumPy recognizes as a np.dtype, and the awkward_type is an ak.types.Type from ak.type or a string in that form, such as "var * float64" for variable-length doubles.

RNTuple can be extended using extend method:

my_directory["tuple6"].extend({"branch1": another_numpy_array,
                              "branch2": another_awkward_array})

Be sure to make these extensions as large as is feasible within memory constraints, because a ROOT file full of small clusters is bloated (larger than it needs to be) and slow to read (especially for Uproot, but also for ROOT).

For instance, if you want to write a million events and have enough memory available to do that 100 thousand events at a time (total of 10 clusters), then do so. Filling the RNTuple a hundred events at a time (total of 10000 clusters) would be considerably slower for writing and reading, and the file would be much larger than it could otherwise be, even with compression.

path

WritableNTuple.path

Path of directory names to this RNTuple as a tuple of strings.

object_path

WritableNTuple.object_path

Path of directory names to this RNTuple as a single string, delimited by slashes.

file_path

WritableNTuple.file_path

Filesystem path of the open file, or None if using a file-like object.

file

WritableNTuple.file

Handle to the uproot.WritableDirectory in which this directory can be found.

close

WritableNTuple.close()

Explicitly close the file.

(Files can also be closed with the Python with statement, as context managers.)

After closing, objects cannot be read from or written to the file.

closed

WritableNTuple.closed

True if the file has been closed; False otherwise.

The file may have been closed explicitly with close or implicitly in the Python with statement, as a context manager.

After closing, objects cannot be read from or written to the file.

compression

WritableNTuple.compression

Compression algorithm and level (uproot.compression.Compression or None) used when writing pages to this RNTuple.

RNTuple compression is file-wide and is taken from the file header; individual per-column compression is not yet supported.

num_entries

WritableNTuple.num_entries

The number of entries accumulated so far.

extend

WritableNTuple.extend(data, accept_new_fields=False)
Parameters:
  • data (dict of str → arrays) – More array data to add to the RNTuple.

  • accept_new_fields (bool) – If False (default), raises ValueError if data contains fields not already in the RNTuple, forcing the user to call add_fields first. If True, new fields are automatically added back-filled with zeros for existing entries, then extended with the provided values for new entries.

This method adds data to an existing RNTuple, whether it was created through assignment or uproot.writing.writable.WritableDirectory.mkrntuple.

The arrays must be a dict, but the values of the dict can be any of the array/DataFrame types described in uproot.WritableTree. However, these types must be compatible with the established TBranch types, the dict must contain a key for every TBranch, and the arrays must have the same lengths (in their first dimension).

For example,

with uproot.update("file.root") as f:
    f["mytuple"].extend({
        "x": np.array([4, 5, 6]),
        "y": np.array([40, 50, 60]),
    })

# automatically add new field and extend
with uproot.update("file.root") as f:
    f["mytuple"].extend({"x": np.array([7, 8]), "z": np.array([70, 80])},
                        accept_new_fields=True)

Warning

As a word of warning, be sure that each call to extend includes at least 100 kB per branch/array. (NumPy and Awkward Arrays have an nbytes property; you want at least 100000 per array.) If you ask Uproot to write very small TBaskets, it will spend more time working on TBasket overhead than actually writing data. The absolute worst case is one-entry-per-extend. See #428 (comment).

Note

Extending an RNTuple opened with uproot.writing.writable.WritableDirectory.update only works if every column uses an encoding Uproot itself writes. RNTuples written by ROOT commonly use column encodings (e.g. split encoding) that Uproot does not yet write, and are rejected with a ValueError rather than risk writing an inconsistent file. In practice, extend/add_fields after reopening a file only work reliably on RNTuples that Uproot itself wrote.

add_fields

WritableNTuple.add_fields(new_fields)
Parameters:

new_fields (dict of str -> numpy dtype) – New field names and types. Only scalar numeric types are accepted (e.g. np.int32, np.float64). Variable-length or nested types are not supported.

Adds new fields to this RNTuple, back-filled with zeros for existing entries. Only top-level fields or subfields of existing untyped record fields are supported.

Note: when using accept_new_fields=True in extend(), new fields must be flat (scalar) types. Jagged or nested new fields will fail the form compatibility check in extend.

Raises:
  • TypeError – if a field type is not a simple scalar numeric type.

  • ValueError – if a field already exists, if the subfield parent is not found or is a typed struct (C++ typename), if the file was opened without a file path (file-like objects are not supported), or if the RNTuple uses column encodings Uproot does not write (see the note below).

For example,

with uproot.update("file.root") as f:
    f["mytuple"].add_fields({"z": np.int32, "w": np.float32})

Note

Like extend, this only works on an RNTuple opened with uproot.writing.writable.WritableDirectory.update if every column uses an encoding Uproot itself writes. RNTuples written by ROOT commonly use column encodings (e.g. split encoding) that Uproot does not yet write, and are rejected with a ValueError. In practice, add_fields/extend after reopening a file only work reliably on RNTuples that Uproot itself wrote.