Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ntpl020_soa.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_ntuple
3/// \notebook
4/// Example of RNTuple I/O on collections with a SoA memory layout
5///
6/// RNTuple on-disk collections can be used in struct-of-arrays (SoA) memory layout.
7/// An RNTuple SoA class consists of persistent members of type `RVec` corresponding to
8/// and underlying record type, as shown in this tutorial.
9///
10/// \macro_code
11///
12/// \date April 2026
13/// \author The ROOT Team
14
15#include <ROOT/REntry.hxx>
16#include <ROOT/RNTupleModel.hxx>
19#include <ROOT/RVec.hxx>
20
21#include <TCanvas.h>
22#include <TClass.h>
23#include <TDictAttributeMap.h>
24#include <TEllipse.h>
25#include <TGraph.h>
26#include <TRandom.h>
27
28#include <iostream>
29#include <memory>
30
31constexpr const char *kFileName = "ntpl020_soa.root";
32constexpr const char *kNTupleName = "ntpl";
33
34// The SoA class for this tutorial. Contains a number of 2D points. All vectors have to have the same length.
35// Note that RVecs can adopt memory.
36struct PointSoA {
39};
40
41// The underlying record type for the SoA class. Members between the SoA class and the underlying record type
42// are matched by name. Every member of type `T` in the underlying record type has to be of type `ROOT::RVec<T>` in
43// the SoA class.
44struct PointRecord {
45 float fX;
46 float fY;
47};
48
49void Write()
50{
51 // Create a model with a SoA field
54
55 auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), kNTupleName, kFileName);
56 auto entry = writer->GetModel().CreateBareEntry();
57
58 for (auto nPoints : {100, 500, 1000, 10000}) {
59 // We will use our own memory are to store the points
60 auto memory = std::make_unique<float[]>(nPoints * 2);
61
62 // Create random points in the unit square
63 gRandom->RndmArray(2 * nPoints, memory.get());
64
65 // Adopt the memory by a PointSoA object. First all x values, then all y values.
66 PointSoA points{ROOT::RVec<float>(memory.get(), nPoints), ROOT::RVec<float>(memory.get() + nPoints, nPoints)};
67
68 entry->BindRawPtr("points", &points);
69 writer->Fill(*entry);
70 }
71}
72
73void Read()
74{
75 auto reader = ROOT::RNTupleReader::Open(kNTupleName, kFileName);
76
77 // Show on-disk layout: collection of underlying record type (AoS)
78 reader->PrintInfo();
79
80 // Used to draw the points
81 auto canvas = new TCanvas("c", "", 1200, 1200);
82 canvas->Divide(2, 2);
83
84 // Read back the points in two steps: first get the size and then read into adopted RVecs.
85 auto viewSize = reader->GetCollectionView("points");
86 PointSoA points;
87 auto viewSoA = reader->GetView("points", &points, "PointSoA");
88
89 for (auto i : reader->GetEntryRange()) {
90 const auto N = viewSize(i); // size of this entry's SoA collection
91 auto memory = std::make_unique<float[]>(N * 2);
92
93 points.fX = ROOT::RVec<float>(memory.get(), N);
94 points.fY = ROOT::RVec<float>(memory.get() + N, N);
95 viewSoA(i);
96
97 // Use the raw memory area to draw the points
98 canvas->cd(i + 1);
99 auto *graph = new TGraph(N, &memory[0], &memory[N]);
100 graph->SetTitle((std::to_string(N) + " Points").c_str());
101 graph->SetMarkerStyle(29);
102 graph->SetMarkerSize(1);
103 graph->SetMarkerColor(kRed);
104 graph->Draw("AP");
105 auto *circle = new TEllipse(0.5, 0.5, 0.5, 0.5);
106 circle->SetFillStyle(0);
107 circle->SetLineColor(kBlue);
108 circle->SetLineWidth(4);
109 circle->Draw();
110
111 // Use adopted RVec's to approximate PI
112 points.fX -= 0.5;
113 points.fY -= 0.5;
114 auto isInCircle = points.fX * points.fX + points.fY * points.fY < 0.25;
115 auto hits = ROOT::VecOps::Sum(isInCircle);
116 float approxPI = 4.0 * static_cast<float>(hits) / static_cast<float>(N);
117 std::cout << "Approximated PI with " << N << " points to " << approxPI << std::endl;
118 }
119 canvas->Update();
120}
121
122void ntpl020_soa()
123{
124 // Usually, the SoA class dictionary definition would mark it as a SoA class of the corresponding
125 // underlying record type like this
126 // #pragma link C++ options=rntupleSoARecord(PointRecord) class PointSoA+;
127 // For the interpreted classes in this tutorial, we mark the SoA class at runtime:
128 auto cl = TClass::GetClass("PointSoA");
129 cl->CreateAttributeMap();
130 cl->GetAttributeMap()->AddProperty("rntuple.SoARecord", "PointRecord");
131
132 Write();
133 Read();
134}
@ kRed
Definition Rtypes.h:66
@ kBlue
Definition Rtypes.h:66
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
R__EXTERN TRandom * gRandom
Definition TRandom.h:73
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
static std::unique_ptr< RNTupleModel > CreateBare()
Creates a "bare model", i.e. an RNTupleModel with no default entry.
static std::unique_ptr< RNTupleReader > Open(std::string_view ntupleName, std::string_view storage, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Open an RNTuple for reading.
static std::unique_ptr< RNTupleWriter > Recreate(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, std::string_view storage, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter backed by storage, overwriting it if one with the same URI exists.
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1509
The Canvas class.
Definition TCanvas.h:23
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
Draw Ellipses.
Definition TEllipse.h:25
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
virtual void RndmArray(Int_t n, Float_t *array)
Return an array of n random numbers uniformly distributed in ]0,1[.
Definition TRandom.cxx:594
T Sum(const RVec< T > &v, const T zero=T(0))
Sum elements of an RVec.
Definition RVec.hxx:1932