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/// NOTE: The RNTuple SoA I/O is still experimental at this point.
11/// Functionality and interface are subject to changes.
12///
13/// \macro_code
14///
15/// \date April 2026
16/// \author The ROOT Team
17
18#include <ROOT/REntry.hxx>
19#include <ROOT/RNTupleModel.hxx>
22#include <ROOT/RVec.hxx>
23
24#include <TCanvas.h>
25#include <TClass.h>
26#include <TDictAttributeMap.h>
27#include <TEllipse.h>
28#include <TGraph.h>
29#include <TRandom.h>
30
31#include <iostream>
32#include <memory>
33
34constexpr const char *kFileName = "ntpl020_soa.root";
35constexpr const char *kNTupleName = "ntpl";
36
37// The SoA class for this tutorial. Contains a number of 2D points. All vectors have to have the same length.
38// Note that RVecs can adopt memory.
39struct PointSoA {
42};
43
44// The underlying record type for the SoA class. Members between the SoA class and the underlying record type
45// are matched by name. Every member of type `T` in the underlying record type has to be of type `ROOT::RVec<T>` in
46// the SoA class.
47struct PointRecord {
48 float fX;
49 float fY;
50};
51
52void Write()
53{
54 // Create a model with a SoA field
55 auto model = ROOT::RNTupleModel::CreateBare();
56 model->AddField(ROOT::RFieldBase::Create("points", "PointSoA").Unwrap());
57
58 auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), kNTupleName, kFileName);
59 auto entry = writer->GetModel().CreateBareEntry();
60
61 for (auto nPoints : {100, 500, 1000, 10000}) {
62 // We will use our own memory are to store the points
63 auto memory = std::make_unique<float[]>(nPoints * 2);
64
65 // Create random points in the unit square
66 gRandom->RndmArray(2 * nPoints, memory.get());
67
68 // Adopt the memory by a PointSoA object. First all x values, then all y values.
70
71 entry->BindRawPtr("points", &points);
72 writer->Fill(*entry);
73 }
74}
75
76void Read()
77{
79
80 // Show on-disk layout: collection of underlying record type (AoS)
81 reader->PrintInfo();
82
83 // Used to draw the points
84 auto canvas = new TCanvas("c", "", 1200, 1200);
85 canvas->Divide(2, 2);
86
87 // Read back the points in two steps: first get the size and then read into adopted RVecs.
88 auto viewSize = reader->GetCollectionView("points");
90 auto viewSoA = reader->GetView("points", &points, "PointSoA");
91
92 for (auto i : reader->GetEntryRange()) {
93 const auto N = viewSize(i); // size of this entry's SoA collection
94 auto memory = std::make_unique<float[]>(N * 2);
95
97 points.fY = ROOT::RVec<float>(memory.get() + N, N);
98 viewSoA(i);
99
100 // Use the raw memory area to draw the points
101 canvas->cd(i + 1);
102 auto *graph = new TGraph(N, &memory[0], &memory[N]);
103 graph->SetTitle((std::to_string(N) + " Points").c_str());
104 graph->SetMarkerStyle(29);
105 graph->SetMarkerSize(1);
106 graph->SetMarkerColor(kRed);
107 graph->Draw("AP");
108 auto *circle = new TEllipse(0.5, 0.5, 0.5, 0.5);
109 circle->SetFillStyle(0);
110 circle->SetLineColor(kBlue);
111 circle->SetLineWidth(4);
112 circle->Draw();
113
114 // Use adopted RVec's to approximate PI
115 points.fX -= 0.5;
116 points.fY -= 0.5;
117 auto isInCircle = points.fX * points.fX + points.fY * points.fY < 0.25;
119 float approxPI = 4.0 * static_cast<float>(hits) / static_cast<float>(N);
120 std::cout << "Approximated PI with " << N << " points to " << approxPI << std::endl;
121 }
122 canvas->Update();
123}
124
125void ntpl020_soa()
126{
127 // Usually, the SoA class dictionary definition would mark it as a SoA class of the corresponding
128 // underlying record type like this
129 // #pragma link C++ options=rntupleSoARecord(PointRecord) class PointSoA+;
130 // For the interpreted classes in this tutorial, we mark the SoA class at runtime:
131 auto cl = TClass::GetClass("PointSoA");
132 cl->CreateAttributeMap();
133 cl->GetAttributeMap()->AddProperty("rntuple.SoARecord", "PointRecord");
134
135 Write();
136 Read();
137}
@ kRed
Definition Rtypes.h:67
@ kBlue
Definition Rtypes.h:67
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#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:62
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:1530
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:2994
Draw Ellipses.
Definition TEllipse.h:24
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:1955