1

I am trying to use Uproot to read some existing trees. I can open the ROOT file with trees, I can "get" the trees and "show" their branches. I've met branches for which I don't know how to "dump" them and/or get their content.

Some branches contain standard ROOT objects:

Vtx/Vtx.NuFileName              | TObjString*[]                        | AsObjects(AsArray(True, False, AsPointer(Model_TObjString), ()))
SYST/SYST._cov_matrix           | TMatrixT<double>[]                   | AsObjects(AsArray(True, False, Model_TMatrixT_3c_double_3e_, ()))

Some branches are "experiment specific" / "custom" (I don't have ROOT "dictionaries" for them):

POTInfo_v2                      | Header                               | AsObjects(Model_Header)
SEL/SEL._rootStep               | StepBase*[]                          | AsObjects(AsArray(True, False, AsPointer(Model_StepBase), ()))
SEL/SEL._firstSteps             | std::vector<StepBase*>[]             | AsObjects(AsArray(True, False, AsVector(False, AsPointer(Model_StepBase)), ()))
CATEG/CATEG._types              | std::vector<TrackTypeDefinition>[]   | AsObjects(AsArray(True, False, AsVector(False, Model_TrackTypeDefinition), ()))
CONF/CONF._toys                 | std::vector<ToyVariationWrite>[]     | AsObjects(AsArray(True, False, AsVector(False, Model_ToyVariationWrite), ()))

Thanks in advance.

Jim Pivarski
  • 5,568
  • 2
  • 35
  • 47

1 Answers1

0

The TTree.show method only displays a summary of the TBranches, a tabular view of TBranch.typename (C++ type name) and TBranch.interpretation (Pythonic interpretation). In both cases, this will show you some levels of depth (e.g. std::vector containing XYZ), but classes are opaque.

If you want to know what fields are in a class definition, even if it is a user-defined class, you can get that information from the ROOT file's "streamer info." Here's an example:

>>> import uproot
>>> import skhep_testdata
>>> root_directory = uproot.open(skhep_testdata.data_path("uproot-issue283.root"))

This file, uproot-issue283.root, was from a search for supernovas in IceCube, and it has custom data types with names like SN_Analysis_Configuration_t, I3Eval_t, and SN_File_t. Knowing the C++ type name of the class (not the Python name, which starts with "Model_"), you can look it up with uproot.ReadOnlyFile.streamer_named:

>>> root_directory.file.streamer_named("I3Eval_t").show()
I3Eval_t (v7): TObject (v1)
    theDataArray: Sni3DataArray* (TStreamerObjectAnyPointer)
    NumberOfChannels: int (TStreamerBasicType)
    NoAvailableSlices: int (TStreamerBasicType)
    AvailableDataSize: int (TStreamerBasicType)
    mGPSCardId: int (TStreamerBasicType)
    mGPSPrescale: int (TStreamerBasicType)
    mGPSEventNo: int (TStreamerBasicType)
    mScalerCardId: int (TStreamerBasicType)
    mScalerStartChannel: int (TStreamerBasicType)
    StartUTC: long (TStreamerBasicType)
    MaxChannels: int (TStreamerBasicType)
    mMaxJitterLogs: int (TStreamerBasicType)
    Channel: I3Eval_t::ChannelContainer_t* (TStreamerObjectAnyPointer)
    ChannelIDMap: map<long,int> (TStreamerSTL)
    BadChannelIDSet: set<long> (TStreamerSTL)
    ChannelID: long* (TStreamerBasicPointer)
    Deadtime: double* (TStreamerBasicPointer)
    Efficiency: double* (TStreamerBasicPointer)

The information here includes the class version (v7), its inheritance (TObject (v1)), its class attributes, their C++ types, and the ROOT streamer than maintains them (e.g. TStreamerBasicType). Note that ROOT can only store attributes, which are usually private in C++, not any methods or functions. When you get an instance of one of these C++ classes, you can access any member with the uproot.Model.member method (see also members, all_members to include superclasses, and has_member):

>>> root_directory["config/detector"].member("theDataArray")
<Sni3DataArray (version 1) at 0x7efd043d1ca0>

>>> root_directory["config/detector"].member("NumberOfChannels")
5160

>>> root_directory["config/detector"].member("Efficiency")
array([1.  , 1.  , 1.  , ..., 1.35, 1.35, 1.35])

If you're getting the objects from a TTree, rather than directly out of a TDirectory as in the above example, you'll (probably) have to get the data with library="np" (NumPy arrays of Python objects) instead of the default library="ak" (Awkward Arrays).

To see all of the streamers, there's an uproot.ReadOnlyFile.show_streamers method:

>>> root_directory.file.show_streamers()
SN_Streaming_All_t (v3): SN_Streaming_t (v2)
    iamdaq: int (TStreamerBasicType)
    no_channels: int (TStreamerBasicType)
    data: unsigned short* (TStreamerBasicPointer)

SN_Streaming_t (v2)
    base_time: unsigned long (TStreamerBasicType)
    gps_time_high: unsigned long (TStreamerBasicType)
    gps_time_low: unsigned long (TStreamerBasicType)
    buf_pos: unsigned long (TStreamerBasicType)
    buf_loop: unsigned long (TStreamerBasicType)

SN_Streaming_GPS_t (v3): SN_Streaming_t (v2)
    real_gps_low: unsigned long long (TStreamerBasicType)
    real_gps_high: unsigned long long (TStreamerBasicType)
    event_no: unsigned long long (TStreamerBasicType)

...

and you can limit its output to a class and the classes that class depends on by passing the C++ name:

>>> root_directory.file.show_streamers("I3Eval_t")
I3Eval_t::ChannelContainer_t (v1)

Sni3DataArray (v1)

TObject (v1)
    fUniqueID: unsigned int (TStreamerBasicType)
    fBits: unsigned int (TStreamerBasicType)

I3Eval_t (v7): TObject (v1)
    theDataArray: Sni3DataArray* (TStreamerObjectAnyPointer)
    NumberOfChannels: int (TStreamerBasicType)
    NoAvailableSlices: int (TStreamerBasicType)
    AvailableDataSize: int (TStreamerBasicType)
    mGPSCardId: int (TStreamerBasicType)
    mGPSPrescale: int (TStreamerBasicType)
    mGPSEventNo: int (TStreamerBasicType)
    mScalerCardId: int (TStreamerBasicType)
    mScalerStartChannel: int (TStreamerBasicType)
    StartUTC: long (TStreamerBasicType)
    MaxChannels: int (TStreamerBasicType)
    mMaxJitterLogs: int (TStreamerBasicType)
    Channel: I3Eval_t::ChannelContainer_t* (TStreamerObjectAnyPointer)
    ChannelIDMap: map<long,int> (TStreamerSTL)
    BadChannelIDSet: set<long> (TStreamerSTL)
    ChannelID: long* (TStreamerBasicPointer)
    Deadtime: double* (TStreamerBasicPointer)
    Efficiency: double* (TStreamerBasicPointer)
Jim Pivarski
  • 5,568
  • 2
  • 35
  • 47