{ "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 }