7. NTuple and event collection facilities¶
This chapter describes the modern way of writing ntuples (ROOT TTrees)
from an algorithm. The old NTuple classes (NtuplePtr, the
NTupleSvc-based booking of the legacy guide) still exist for
backward compatibility but should not be used in new code.
The new interface lives in Gaudi/NTuple/Writer.h (in the GaudiUtils
library) and provides three building blocks, all layered on top of the
functional framework (see Writing algorithms).
7.1. Gaudi::NTuple::Writer¶
For the common case of one ntuple entry per event: the class
inherits from a signature describing the input data and the ntuple
columns, and only implements a transform function converting the
inputs into a tuple of column values:
1 2 3 4 5 6 7 8 9 10 11 12 | #include <Gaudi/NTuple/Writer.h>
struct MyWriter final
: Gaudi::NTuple::Writer<std::tuple<int, std::size_t, float>( const std::vector<int>& )> {
MyWriter( const std::string& name, ISvcLocator* svcLoc )
: Writer( name, svcLoc, { "InputLocation", "MyVector" } ) {}
std::tuple<int, std::size_t, float> transform( const std::vector<int>& v ) const override {
return { std::accumulate( v.begin(), v.end(), 0 ), v.size(), m_rand() };
}
};
DECLARE_COMPONENT( MyWriter )
|
7.2. Gaudi::NTuple::SimpleWriter¶
When the number of entries per event is not fixed, inherit from
Gaudi::NTuple::SimpleWriter and call fillTree as many times as
entries are needed:
1 2 3 4 5 6 7 | struct MySimpleWriter final
: Gaudi::NTuple::SimpleWriter<std::tuple<int, std::size_t, float>( const std::vector<int>& )> {
using SimpleWriter::SimpleWriter;
void operator()( const std::vector<int>& v ) const override {
for ( std::size_t i = 0; auto const& x : v ) { fillTree( { x, i++, 0.5f } ); }
}
};
|
fillTree is internally synchronized, hence thread-safe.
The properties of both writer classes are:
OutputFilethe identifier of the TFile in the
FileSvcto write to;NTupleNamethe name of the written TTree (a
/in the name creates directories in the file);BranchNamesthe names of the ntuple columns, one per column type of the signature tuple. Array properties are set from the job options with lists.
7.3. Gaudi::NTuple::Wrapper¶
The lower-level building block, wrapping a TTree: initTree creates
the branches from a list of names, fillTree appends an entry
(thread-safe), writeTree persists the tree. Together with
Gaudi::NTuple::FileHolder (a mixin that adds the OutputFile
property and FileSvc handling to an algorithm), it allows several
NTuples per algorithm.
1 2 3 4 5 6 7 | Gaudi::NTuple::Wrapper<int, float> m_ntuple;
...
m_ntuple.initTree( file, name(), "MyNtuple", { "a", "b" } );
...
m_ntuple.fillTree( { 1, 2.5f } );
...
m_ntuple.writeTree( file, name() );
|
7.4. Opening the output file¶
The output file is opened through the FileSvc service, so that it
is shared with other components (histogram sinks may write to the same
file — see Logging and monitoring sinks):
C.FileSvc(Config={"NTuple": "myfile.root?mode=recreate"})
with OutputFile="NTuple" (the default) on the writer algorithm,
and the service and the writer in the job’s ExtSvc/TopAlg.
7.5. Event collections and persistency of event data¶
As discussed in Accessing data, Gaudi no longer ships a generic “persistent event store”: writing event data collections is the job of dedicated, experiment-specific algorithms.