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 <memory>
26#include <unordered_set>
27#include <utility>
28
29namespace ROOT {
30namespace Experimental {
31
32class RCollectionNTupleWriter;
33
34// clang-format off
35/**
36\class ROOT::Experimental::RNTupleModel
37\ingroup NTuple
38\brief The RNTupleModel encapulates the schema of an ntuple.
39
40The ntuple model comprises a collection of hierarchically organized fields. From a model, "entries"
41can be extracted. For convenience, the model provides a default entry. Models have a unique model identifier
42that faciliates checking whether entries are compatible with it (i.e.: have been extracted from that model).
43*/
44// clang-format on
46 /// Hierarchy of fields consisting of simple types and collections (sub trees)
47 std::unique_ptr<RFieldZero> fFieldZero;
48 /// Contains field values corresponding to the created top-level fields
49 std::unique_ptr<REntry> fDefaultEntry;
50 /// Keeps track of which field names are taken.
51 std::unordered_set<std::string> fFieldNames;
52
53 /// Checks that user-provided field names are valid in the context
54 /// of this NTuple model. Throws an RException for invalid names.
56
57 /// Free text set by the user
58 std::string fDescription;
59
60public:
62 RNTupleModel(const RNTupleModel&) = delete;
64 ~RNTupleModel() = default;
65
66 std::unique_ptr<RNTupleModel> Clone() const;
67 static std::unique_ptr<RNTupleModel> Create() { return std::make_unique<RNTupleModel>(); }
68
69 /// Creates a new field and a corresponding tree value that is managed by a shared pointer.
70 ///
71 /// **Example: create some fields and fill an %RNTuple**
72 /// ~~~ {.cpp}
73 /// #include <ROOT/RNTuple.hxx>
74 /// using ROOT::Experimental::RNTupleModel;
75 /// using ROOT::Experimental::RNTupleWriter;
76 ///
77 /// #include <vector>
78 ///
79 /// auto model = RNTupleModel::Create();
80 /// auto pt = model->MakeField<float>("pt");
81 /// auto vec = model->MakeField<std::vector<int>>("vec");
82 ///
83 /// // The RNTuple is written to disk when the RNTupleWriter goes out of scope
84 /// {
85 /// auto ntuple = RNTupleWriter::Recreate(std::move(model), "myNTuple", "myFile.root");
86 /// for (int i = 0; i < 100; i++) {
87 /// *pt = static_cast<float>(i);
88 /// *vec = {i, i+1, i+2};
89 /// ntuple->Fill();
90 /// }
91 /// }
92 /// ~~~
93 /// **Example: create a field with an initial value**
94 /// ~~~ {.cpp}
95 /// #include <ROOT/RNTuple.hxx>
96 /// using ROOT::Experimental::RNTupleModel;
97 ///
98 /// auto model = RNTupleModel::Create();
99 /// // pt's initial value is 42.0
100 /// auto pt = model->MakeField<float>("pt", 42.0);
101 /// ~~~
102 template <typename T, typename... ArgsT>
103 std::shared_ptr<T> MakeField(std::string_view fieldName, ArgsT&&... args) {
104 return MakeField<T>({fieldName, ""}, std::forward<ArgsT>(args)...);
105 }
106
107 /// Creates a new field given a `{name, description}` pair and a corresponding tree value that
108 /// is managed by a shared pointer.
109 ///
110 /// **Example: create a field with a description**
111 /// ~~~ {.cpp}
112 /// #include <ROOT/RNTuple.hxx>
113 /// using ROOT::Experimental::RNTupleModel;
114 ///
115 /// auto model = RNTupleModel::Create();
116 /// auto hadronFlavour = model->MakeField<float>({
117 /// "hadronFlavour", "flavour from hadron ghost clustering"
118 /// });
119 /// ~~~
120 template <typename T, typename... ArgsT>
121 std::shared_ptr<T> MakeField(std::pair<std::string_view, std::string_view> fieldNameDesc,
122 ArgsT&&... args)
123 {
124 EnsureValidFieldName(fieldNameDesc.first);
125 auto field = std::make_unique<RField<T>>(fieldNameDesc.first);
126 field->SetDescription(fieldNameDesc.second);
127 auto ptr = fDefaultEntry->AddValue<T>(field.get(), std::forward<ArgsT>(args)...);
128 fFieldZero->Attach(std::move(field));
129 return ptr;
130 }
131
132 /// Adds a field whose type is not known at compile time. Thus there is no shared pointer returned.
133 ///
134 /// Throws an exception if the field is null.
135 void AddField(std::unique_ptr<Detail::RFieldBase> field);
136
137 /// Throws an exception if fromWhere is null.
138 template <typename T>
139 void AddField(std::string_view fieldName, T* fromWhere) {
140 AddField<T>({fieldName, ""}, fromWhere);
141 }
142
143 /// Throws an exception if fromWhere is null.
144 template <typename T>
145 void AddField(std::pair<std::string_view, std::string_view> fieldNameDesc, T* fromWhere) {
146 EnsureValidFieldName(fieldNameDesc.first);
147 if (!fromWhere) {
148 throw RException(R__FAIL("null field fromWhere"));
149 }
150 auto field = std::make_unique<RField<T>>(fieldNameDesc.first);
151 field->SetDescription(fieldNameDesc.second);
152 fDefaultEntry->CaptureValue(field->CaptureValue(fromWhere));
153 fFieldZero->Attach(std::move(field));
154 }
155
156 template <typename T>
157 T* Get(std::string_view fieldName) {
158 return fDefaultEntry->Get<T>(fieldName);
159 }
160
161 /// Ingests a model for a sub collection and attaches it to the current model
162 ///
163 /// Throws an exception if collectionModel is null.
164 std::shared_ptr<RCollectionNTupleWriter> MakeCollection(
165 std::string_view fieldName,
166 std::unique_ptr<RNTupleModel> collectionModel);
167
168 RFieldZero *GetFieldZero() const { return fFieldZero.get(); }
171 std::unique_ptr<REntry> CreateEntry();
173 std::string GetDescription() const { return fDescription; }
174 void SetDescription(std::string_view description) { fDescription = std::string(description); }
175 RNTupleUuid GetUuid() const { return RNTupleUuid(); /* TODO */ }
176};
177
178} // namespace Experimental
179} // namespace ROOT
180
181#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:42
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:271
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.
T * Get(std::string_view fieldName)
RNTupleModel(const RNTupleModel &)=delete
std::string GetDescription() const
std::unique_ptr< RNTupleModel > Clone() const
void AddField(std::string_view fieldName, T *fromWhere)
Throws an exception if fromWhere is null.
std::unique_ptr< REntry > CreateEntry()
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...
RNTupleVersion GetVersion() const
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.
Detail::RFieldBase * GetField(std::string_view fieldName)
RFieldZero * GetFieldZero() const
static std::unique_ptr< RNTupleModel > Create()
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)
For forward and backward compatibility, attach version information to the consitituents of the file f...
basic_string_view< char > string_view
std::string RNTupleUuid
Every NTuple is identified by a UUID. TODO(jblomer): should this be a TUUID?
double T(double x)
Definition: ChebyshevPol.h:34
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...