{
"cells": [
{
"cell_type": "markdown",
"id": "da48e1e1",
"metadata": {},
"source": [
"# ntpl005_introspection\n",
"Write and read an RNTuple from a user-defined class. Adapted from tv3.C\n",
"Illustrates various RNTuple introspection methods.\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** The ROOT Team \n",
"This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, May 19, 2026 at 08:14 PM."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "ee28ad8a",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:55.540562Z",
"iopub.status.busy": "2026-05-19T20:14:55.540452Z",
"iopub.status.idle": "2026-05-19T20:14:55.548290Z",
"shell.execute_reply": "2026-05-19T20:14:55.547713Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"\n",
"#include \n",
"#include \n",
"#include \n",
"#include \n",
"\n",
"#include \n",
"#include \n",
"#include \n",
"#include \n",
"#include \n",
"\n",
"#include \n",
"\n",
"constexpr char const* kNTupleFileName = \"ntpl005_introspection.root\";"
]
},
{
"cell_type": "markdown",
"id": "59fae5df",
"metadata": {},
"source": [
"Store entries of type Vector3 in the ntuple"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "813a4b43",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:55.549527Z",
"iopub.status.busy": "2026-05-19T20:14:55.549414Z",
"iopub.status.idle": "2026-05-19T20:14:55.863867Z",
"shell.execute_reply": "2026-05-19T20:14:55.863122Z"
}
},
"outputs": [],
"source": [
"class Vector3 {\n",
"private:\n",
" double fX = 0;\n",
" double fY = 0;\n",
" double fZ = 0;\n",
"\n",
"public:\n",
" double x() const { return fX; }\n",
" double y() const { return fY; }\n",
" double z() const { return fZ; }\n",
"\n",
" void SetXYZ(double x, double y, double z) {\n",
" fX = x;\n",
" fY = y;\n",
" fZ = z;\n",
" }\n",
"};"
]
},
{
"cell_type": "markdown",
"id": "ce1e5432",
"metadata": {},
"source": [
" Definition of a helper function: "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ee0ad29e",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:55.866118Z",
"iopub.status.busy": "2026-05-19T20:14:55.866002Z",
"iopub.status.idle": "2026-05-19T20:14:56.036441Z",
"shell.execute_reply": "2026-05-19T20:14:56.035708Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"\n",
"\n",
"void Generate()\n",
"{\n",
" auto model = ROOT::RNTupleModel::Create();\n",
" auto fldVector3 = model->MakeField(\"v3\");\n",
"\n",
" // Explicitly enforce a certain compression algorithm\n",
" ROOT::RNTupleWriteOptions options;\n",
" options.SetCompression(ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose);\n",
"\n",
" auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), \"Vector3\", kNTupleFileName, options);\n",
" TRandom r;\n",
" for (unsigned int i = 0; i < 500000; ++i) {\n",
" fldVector3->SetXYZ(r.Gaus(0,1), r.Landau(0,1), r.Gaus(100,10));\n",
" writer->Fill();\n",
" }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "52259184",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:56.038075Z",
"iopub.status.busy": "2026-05-19T20:14:56.037954Z",
"iopub.status.idle": "2026-05-19T20:14:56.549504Z",
"shell.execute_reply": "2026-05-19T20:14:56.548815Z"
}
},
"outputs": [],
"source": [
"Generate();\n",
"\n",
"auto reader = ROOT::RNTupleReader::Open(\"Vector3\", kNTupleFileName);"
]
},
{
"cell_type": "markdown",
"id": "4544683e",
"metadata": {},
"source": [
"Display the schema of the ntuple"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d78bef35",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:56.551822Z",
"iopub.status.busy": "2026-05-19T20:14:56.551701Z",
"iopub.status.idle": "2026-05-19T20:14:56.756805Z",
"shell.execute_reply": "2026-05-19T20:14:56.756157Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RNTuple : Vector3\n",
"Entries : 500000\n",
"\n",
"Field 1 : v3 (Vector3)\n",
" Field 1.1 : fX (double)\n",
" Field 1.2 : fY (double)\n",
" Field 1.3 : fZ (double)\n"
]
}
],
"source": [
"reader->PrintInfo();"
]
},
{
"cell_type": "markdown",
"id": "45dc09fa",
"metadata": {},
"source": [
"Display information about the storage layout of the data"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "4fd4b0ca",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:56.758555Z",
"iopub.status.busy": "2026-05-19T20:14:56.758436Z",
"iopub.status.idle": "2026-05-19T20:14:56.964791Z",
"shell.execute_reply": "2026-05-19T20:14:56.964065Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"============================================================\n",
"NTUPLE: Vector3\n",
"Compression: 505\n",
"------------------------------------------------------------\n",
" # Entries: 500000\n",
" # Fields: 5\n",
" # Columns: 3\n",
" # Alias Columns: 0\n",
" # Pages: 12\n",
" # Clusters: 1\n",
" Size on storage: 10002232 B\n",
" Compression rate: 1.20\n",
" Header size: 159 B\n",
" Footer size: 286 B\n",
" Metadata / data: 0.000\n",
"------------------------------------------------------------\n",
"CLUSTER DETAILS\n",
"------------------------------------------------------------\n",
" # 0 Entry range: [0..499999] -- 500000\n",
" # Pages: 12\n",
" Size on storage: 10002232 B\n",
" Compression: 1.20\n",
"------------------------------------------------------------\n",
"COLUMN DETAILS\n",
"------------------------------------------------------------\n",
" v3.fX [#0] -- SplitReal64 {id:0}\n",
" # Elements: 500000\n",
" # Pages: 4\n",
" Avg elements / page: 125000\n",
" Avg page size: 836054 B\n",
" Size on storage: 3344217 B\n",
" Compression: 1.20\n",
"............................................................\n",
" v3.fY [#0] -- SplitReal64 {id:1}\n",
" # Elements: 500000\n",
" # Pages: 4\n",
" Avg elements / page: 125000\n",
" Avg page size: 895624 B\n",
" Size on storage: 3582496 B\n",
" Compression: 1.12\n",
"............................................................\n",
" v3.fZ [#0] -- SplitReal64 {id:2}\n",
" # Elements: 500000\n",
" # Pages: 4\n",
" Avg elements / page: 125000\n",
" Avg page size: 768879 B\n",
" Size on storage: 3075519 B\n",
" Compression: 1.30\n",
"............................................................\n"
]
}
],
"source": [
"reader->PrintInfo(ROOT::ENTupleInfo::kStorageDetails);"
]
},
{
"cell_type": "markdown",
"id": "b71caf26",
"metadata": {},
"source": [
"Display the first entry"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0f5094b3",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:56.966420Z",
"iopub.status.busy": "2026-05-19T20:14:56.966302Z",
"iopub.status.idle": "2026-05-19T20:14:57.172114Z",
"shell.execute_reply": "2026-05-19T20:14:57.171239Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"v3\": {\n",
" \"fX\": -0.15,\n",
" \"fY\": 5.48,\n",
" \"fZ\": 93.87\n",
" }\n",
"}\n"
]
}
],
"source": [
"reader->Show(0);"
]
},
{
"cell_type": "markdown",
"id": "af6e5a60",
"metadata": {},
"source": [
"Collect I/O runtime counters when processing the data set.\n",
"Maintaining the counters comes with a small performance overhead, so it has to be explicitly enabled"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "03782ddd",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:57.173678Z",
"iopub.status.busy": "2026-05-19T20:14:57.173531Z",
"iopub.status.idle": "2026-05-19T20:14:57.378711Z",
"shell.execute_reply": "2026-05-19T20:14:57.377706Z"
}
},
"outputs": [],
"source": [
"reader->EnableMetrics();"
]
},
{
"cell_type": "markdown",
"id": "f0a48937",
"metadata": {},
"source": [
"Plot the y components of vector3"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "71116b34",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:57.380220Z",
"iopub.status.busy": "2026-05-19T20:14:57.380074Z",
"iopub.status.idle": "2026-05-19T20:14:57.762024Z",
"shell.execute_reply": "2026-05-19T20:14:57.761371Z"
}
},
"outputs": [],
"source": [
"TCanvas *c1 = new TCanvas(\"c1\",\"RNTuple Demo\", 10, 10, 600, 800);\n",
"c1->Divide(1,2);\n",
"c1->cd(1);\n",
"TH1F h1(\"x\", \"x component of Vector3\", 100, -3, 3);\n",
"{\n",
" /// We enclose viewX in a scope in order to indicate to the RNTuple when we are not\n",
" /// anymore interested in v3.fX\n",
" auto viewX = reader->GetView(\"v3.fX\");\n",
" for (auto i : reader->GetEntryRange()) {\n",
" h1.Fill(viewX(i));\n",
" }\n",
"}\n",
"h1.DrawCopy();\n",
"\n",
"c1->cd(2);\n",
"TH1F h2(\"y\", \"y component of Vector3\", 100, -5, 20);\n",
"auto viewY = reader->GetView(\"v3.fY\");\n",
"for (auto i : reader->GetEntryRange()) {\n",
" h2.Fill(viewY(i));\n",
"}\n",
"h2.DrawCopy();"
]
},
{
"cell_type": "markdown",
"id": "b2d1050a",
"metadata": {},
"source": [
"Display the I/O operation statistics performed by the RNTuple reader"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "975cb210",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:57.763597Z",
"iopub.status.busy": "2026-05-19T20:14:57.763483Z",
"iopub.status.idle": "2026-05-19T20:14:57.969880Z",
"shell.execute_reply": "2026-05-19T20:14:57.969268Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RNTupleReader.RPageSourceFile.nReadV||number of vector read requests|2\n",
"RNTupleReader.RPageSourceFile.nRead||number of byte ranges read|2\n",
"RNTupleReader.RPageSourceFile.szReadPayload|B|volume read from storage (required)|6926777\n",
"RNTupleReader.RPageSourceFile.szReadOverhead|B|volume read from storage (overhead)|0\n",
"RNTupleReader.RPageSourceFile.szUnzip|B|volume after unzipping|8000000\n",
"RNTupleReader.RPageSourceFile.nClusterLoaded||number of partial clusters preloaded from storage|2\n",
"RNTupleReader.RPageSourceFile.nPageRead||number of pages read from storage|8\n",
"RNTupleReader.RPageSourceFile.nPageUnsealed||number of pages unzipped and decoded|8\n",
"RNTupleReader.RPageSourceFile.timeWallRead|ns|wall clock time spent reading|2830653\n",
"RNTupleReader.RPageSourceFile.timeWallUnzip|ns|wall clock time spent decompressing|6992917\n",
"RNTupleReader.RPageSourceFile.timeCpuRead|ns|CPU time spent reading|2839000\n",
"RNTupleReader.RPageSourceFile.timeCpuUnzip|ns|CPU time spent decompressing|6991000\n",
"RNTupleReader.RPageSourceFile.bwRead|MB/s|bandwidth compressed bytes read per second|2447.059742\n",
"RNTupleReader.RPageSourceFile.bwReadUnzip|MB/s|bandwidth uncompressed bytes read per second|2826.203000\n",
"RNTupleReader.RPageSourceFile.bwUnzip|MB/s|decompression bandwidth of uncompressed bytes per second|1144.014722\n",
"RNTupleReader.RPageSourceFile.rtReadEfficiency||ratio of payload over all bytes read|1.000000\n",
"RNTupleReader.RPageSourceFile.rtCompression||ratio of compressed bytes / uncompressed bytes|0.865847\n",
"RNTupleReader.RPageSourceFile.szSkip|B|cumulative seek distance (excluding header/footer reads)|0\n",
"RNTupleReader.RPageSourceFile.szFile|B|total file size|10004002.000000\n",
"RNTupleReader.RPageSourceFile.randomness||ratio of seek distance to bytes read (excluding file structure reads)|0.000000\n",
"RNTupleReader.RPageSourceFile.sparseness||ratio of bytes read to total file size (excluding file structure reads)|0.692401\n",
"RNTupleReader.RPageSourceFile.RClusterPool.nCluster||number of currently cached clusters|1\n",
"RNTupleReader.RPageSourceFile.RPagePool.nPage||number of currently cached pages|1\n"
]
}
],
"source": [
"reader->PrintInfo(ROOT::ENTupleInfo::kMetrics);"
]
},
{
"cell_type": "markdown",
"id": "6964ee92",
"metadata": {},
"source": [
"We read 2 out of the 3 Vector3 members and thus should have requested approximately 2/3 of the file"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e2de8377",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:57.971179Z",
"iopub.status.busy": "2026-05-19T20:14:57.971065Z",
"iopub.status.idle": "2026-05-19T20:14:58.174991Z",
"shell.execute_reply": "2026-05-19T20:14:58.174425Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"File size: 9.54 MiB\n",
"Read from file: 6.61 MiB\n",
"Ratio: 0.69\n"
]
}
],
"source": [
"FileStat_t fileStat;\n",
"auto retval = gSystem->GetPathInfo(kNTupleFileName, fileStat);\n",
"assert(retval == 0);\n",
"float fileSize = static_cast(fileStat.fSize);\n",
"float nbytesRead = reader->GetMetrics().GetCounter(\"RNTupleReader.RPageSourceFile.szReadPayload\")->GetValueAsInt() +\n",
" reader->GetMetrics().GetCounter(\"RNTupleReader.RPageSourceFile.szReadOverhead\")->GetValueAsInt();\n",
"\n",
"std::cout << \"File size: \" << fileSize / 1024. / 1024. << \" MiB\" << std::endl;\n",
"std::cout << \"Read from file: \" << nbytesRead / 1024. / 1024. << \" MiB\" << std::endl;\n",
"std::cout << \"Ratio: \" << nbytesRead / fileSize << std::endl;"
]
},
{
"cell_type": "markdown",
"id": "e836f1fe",
"metadata": {},
"source": [
"Draw all canvases "
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "2aa4ee76",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:14:58.176337Z",
"iopub.status.busy": "2026-05-19T20:14:58.176224Z",
"iopub.status.idle": "2026-05-19T20:14:58.381033Z",
"shell.execute_reply": "2026-05-19T20:14:58.380359Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"
\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"gROOT->GetListOfCanvases()->Draw()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ROOT C++",
"language": "c++",
"name": "root"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".C",
"mimetype": " text/x-c++src",
"name": "c++"
}
},
"nbformat": 4,
"nbformat_minor": 5
}