Logo ROOT  
Reference Guide
RNTupleModel.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleModel.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-04
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RNTupleModel
17#define ROOT7_RNTupleModel
18
19#include <ROOT/REntry.hxx>
20#include <ROOT/RField.hxx>
21#include <ROOT/RNTupleUtil.hxx>
22#include <ROOT/RFieldValue.hxx>
23#include <ROOT/RStringView.hxx>
24
25#include <cstdint>
26#include <memory>
27#include <unordered_set>
28#include <utility>
29
30namespace ROOT {
31namespace Experimental {
32
33class RCollectionNTupleWriter;
34
35// clang-format off
36/**
37\class ROOT::Experimental::RNTupleModel
38\ingroup NTuple
39\brief The RNTupleModel encapulates the schema of an ntuple.
40
41The ntuple model comprises a collection of hierarchically organized fields. From a model, "entries"
42can be extracted. For convenience, the model provides a default entry. Models have a unique model identifier
43that faciliates checking whether entries are compatible with it (i.e.: have been extracted from that model).
44*/
45// clang-format on
47 /// Hierarchy of fields consisting of simple types and collections (sub trees)
48 std::unique_ptr<RFieldZero> fFieldZero;
49 /// Contains field values corresponding to the created top-level fields
50 std::unique_ptr<REntry> fDefaultEntry;
51 /// Keeps track of which field names are taken.
52 std::unordered_set<std::string> fFieldNames;
53 /// Free text set by the user
54 std::string fDescription;
55 /// Upon freezing, every model has a unique ID to distingusish it from other models. Cloning preserves the ID.
56 /// Entries are linked to models via the ID.
57 std::uint64_t fModelId = 0;
58
59 /// Checks that user-provided field names are valid in the context
60 /// of this NTuple model. Throws an RException for invalid names.
62
63 /// Throws an RException if fFrozen is true
64 void EnsureNotFrozen() const;
65
66 /// Throws an RException if fDefaultEntry is nullptr
67 void EnsureNotBare() const;
68
70
71public:
72 RNTupleModel(const RNTupleModel&) = delete;
74 ~RNTupleModel() = default;
75
76 std::unique_ptr<RNTupleModel> Clone() const;
77 static std::unique_ptr<RNTupleModel> Create();
78 /// A bare model has no default entry
79 static std::unique_ptr<RNTupleModel> CreateBare() { return std::unique_ptr<RNTupleModel>(new RNTupleModel()); }
80
81 /// Creates a new field and a corresponding tree value that is managed by a shared pointer.
82 ///
83 /// **Example: create some fields and fill an %RNTuple**
84 /// ~~~ {.cpp}
85 /// #include <ROOT/RNTuple.hxx>
86 /// using ROOT::Experimental::RNTupleModel;
87 /// using ROOT::Experimental::RNTupleWriter;
88 ///
89 /// #include <vector>
90 ///
91 /// auto model = RNTupleModel::Create();
92 /// auto pt = model->MakeField<float>("pt");
93 /// auto vec = model->MakeField<std::vector<int>>("vec");
94 ///
95 /// // The RNTuple is written to disk when the RNTupleWriter goes out of scope
96 /// {
97 /// auto ntuple = RNTupleWriter::Recreate(std::move(model), "myNTuple", "myFile.root");
98 /// for (int i = 0; i < 100; i++) {
99 /// *pt = static_cast<float>(i);
100 /// *vec = {i, i+1, i+2};
101 /// ntuple->Fill();
102 /// }
103 /// }
104 /// ~~~
105 /// **Example: create a field with an initial value**
106 /// ~~~ {.cpp}
107 /// #include <ROOT/RNTuple.hxx>
108 /// using ROOT::Experimental::RNTupleModel;
109 ///
110 /// auto model = RNTupleModel::Create();
111 /// // pt's initial value is 42.0
112 /// auto pt = model->MakeField<float>("pt", 42.0);
113 /// ~~~
114 template <typename T, typename... ArgsT>
115 std::shared_ptr<T> MakeField(std::string_view fieldName, ArgsT&&... args) {
116 return MakeField<T>({fieldName, ""}, std::forward<ArgsT>(args)...);
117 }
118
119 /// Creates a new field given a `{name, description}` pair and a corresponding tree value that
120 /// is managed by a shared pointer.
121 ///
122 /// **Example: create a field with a description**
123 /// ~~~ {.cpp}
124 /// #include <ROOT/RNTuple.hxx>
125 /// using ROOT::Experimental::RNTupleModel;
126 ///
127 /// auto model = RNTupleModel::Create();
128 /// auto hadronFlavour = model->MakeField<float>({
129 /// "hadronFlavour", "flavour from hadron ghost clustering"
130 /// });
131 /// ~~~
132 template <typename T, typename... ArgsT>
133 std::shared_ptr<T> MakeField(std::pair<std::string_view, std::string_view> fieldNameDesc,
134 ArgsT&&... args)
135 {
137 EnsureValidFieldName(fieldNameDesc.first);
138 auto field = std::make_unique<RField<T>>(fieldNameDesc.first);
139 field->SetDescription(fieldNameDesc.second);
140 std::shared_ptr<T> ptr;
141 if (fDefaultEntry)
142 ptr = fDefaultEntry->AddValue<T>(field.get(), std::forward<ArgsT>(args)...);
143 fFieldZero->Attach(std::move(field));
144 return ptr;
145 }
146
147 /// Adds a field whose type is not known at compile time. Thus there is no shared pointer returned.
148 ///
149 /// Throws an exception if the field is null.
150 void AddField(std::unique_ptr<Detail::RFieldBase> field);
151
152 /// Throws an exception if fromWhere is null.
153 template <typename T>
154 void AddField(std::string_view fieldName, T* fromWhere) {
155 AddField<T>({fieldName, ""}, fromWhere);
156 }
157
158 /// Throws an exception if fromWhere is null.
159 template <typename T>
160 void AddField(std::pair<std::string_view, std::string_view> fieldNameDesc, T* fromWhere) {
163 if (!fromWhere)
164 throw RException(R__FAIL("null field fromWhere"));
165 EnsureValidFieldName(fieldNameDesc.first);
166
167 auto field = std::make_unique<RField<T>>(fieldNameDesc.first);
168 field->SetDescription(fieldNameDesc.second);
169 fDefaultEntry->CaptureValue(field->CaptureValue(fromWhere));
170 fFieldZero->Attach(std::move(field));
171 }
172
173 template <typename T>
174 T *Get(std::string_view fieldName) const
175 {
177 return fDefaultEntry->Get<T>(fieldName);
178 }
179
180 void Freeze();
181 bool IsFrozen() const { return fModelId != 0; }
182 std::uint64_t GetModelId() const { return fModelId; }
183
184 /// Ingests a model for a sub collection and attaches it to the current model
185 ///
186 /// Throws an exception if collectionModel is null.
187 std::shared_ptr<RCollectionNTupleWriter> MakeCollection(
188 std::string_view fieldName,
189 std::unique_ptr<RNTupleModel> collectionModel);
190
191 std::unique_ptr<REntry> CreateEntry() const;
192 /// In a bare entry, all values point to nullptr. The resulting entry shall use CaptureValueUnsafe() in order
193 /// set memory addresses to be serialized / deserialized
194 std::unique_ptr<REntry> CreateBareEntry() const;
195 REntry *GetDefaultEntry() const;
196
197 RFieldZero *GetFieldZero() const { return fFieldZero.get(); }
198 const Detail::RFieldBase *GetField(std::string_view fieldName) const;
199
200 std::string GetDescription() const { return fDescription; }
201 void SetDescription(std::string_view description);
202};
203
204} // namespace Experimental
205} // namespace ROOT
206
207#endif
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition: RError.hxx:291
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
Definition: REntry.hxx:43
Base class for all ROOT issued exceptions.
Definition: RError.hxx:114
The container field for an ntuple model, which itself has no physical representation.
Definition: RField.hxx:270
The RNTupleModel encapulates the schema of an ntuple.
std::unordered_set< std::string > fFieldNames
Keeps track of which field names are taken.
std::string fDescription
Free text set by the user.
void EnsureValidFieldName(std::string_view fieldName)
Checks that user-provided field names are valid in the context of this NTuple model.
std::uint64_t fModelId
Upon freezing, every model has a unique ID to distingusish it from other models.
std::uint64_t GetModelId() const
RNTupleModel(const RNTupleModel &)=delete
std::string GetDescription() const
void EnsureNotBare() const
Throws an RException if fDefaultEntry is nullptr.
std::unique_ptr< RNTupleModel > Clone() const
void EnsureNotFrozen() const
Throws an RException if fFrozen is true.
std::unique_ptr< REntry > CreateBareEntry() const
In a bare entry, all values point to nullptr.
std::unique_ptr< REntry > CreateEntry() const
static std::unique_ptr< RNTupleModel > Create()
static std::unique_ptr< RNTupleModel > CreateBare()
A bare model has no default entry.
void AddField(std::string_view fieldName, T *fromWhere)
Throws an exception if fromWhere is null.
void SetDescription(std::string_view description)
std::unique_ptr< REntry > fDefaultEntry
Contains field values corresponding to the created top-level fields.
std::shared_ptr< T > MakeField(std::string_view fieldName, ArgsT &&... args)
Creates a new field and a corresponding tree value that is managed by a shared pointer.
std::shared_ptr< T > MakeField(std::pair< std::string_view, std::string_view > fieldNameDesc, ArgsT &&... args)
Creates a new field given a {name, description} pair and a corresponding tree value that is managed b...
std::shared_ptr< RCollectionNTupleWriter > MakeCollection(std::string_view fieldName, std::unique_ptr< RNTupleModel > collectionModel)
Ingests a model for a sub collection and attaches it to the current model.
const Detail::RFieldBase * GetField(std::string_view fieldName) const
RFieldZero * GetFieldZero() const
T * Get(std::string_view fieldName) const
void AddField(std::pair< std::string_view, std::string_view > fieldNameDesc, T *fromWhere)
Throws an exception if fromWhere is null.
RNTupleModel & operator=(const RNTupleModel &)=delete
void AddField(std::unique_ptr< Detail::RFieldBase > field)
Adds a field whose type is not known at compile time.
std::unique_ptr< RFieldZero > fFieldZero
Hierarchy of fields consisting of simple types and collections (sub trees)
basic_string_view< char > string_view
double T(double x)
Definition: ChebyshevPol.h:34
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.