5. Accessing data¶
Warning
This chapter replaces the data access chapter of the legacy guide,
which described the direct use of the event data service
(evtSvc()->retrieve(...), evtSvc()->registerObject(...)) and
the DataObject class hierarchy. That style is now obsolete: user
algorithms should never talk to the stores directly, and DataObject
must be considered an internal implementation detail of the transient
data stores (and not even of all of them: some stores hold payloads
that are not DataObject-based, wrapped internally for the
framework).
This chapter describes direct access to data by user code. Data access is actually handled automatically when using the functional framework (see Writing algorithms). Thus it is recommended to use the functional framework and not deal with data handles directly. The rest of the chapter (selections, ranges, conditions, …) also applies to the functional framework.
5.1. The transient event store¶
Historically, per-event data lives in the event data store or transient Event store (aka TES).
As any Gaudi component, the TES can have, and thus does have, multiple implementations.
The most used one is probably the “whiteboard”,
HiveWhiteBoard, configured as HiveWhiteBoard("EventDataSvc",
EventSlots=N). The whiteboard keeps a separate store per slot when
more than one event slot is used and the framework activates the right one
for the current event, so algorithms never see data of another event.
Anyway the stores are opaque to user code. All access goes through data handles. They may even not be used by certain schedulers implementing alternative ways of dealing with data.
5.2. Data handles¶
A data handle is a member of an algorithm (or tool, or service) that declares which product it accesses and how:
1 2 3 4 5 6 7 8 | #include <GaudiKernel/DataObjectHandle.h>
class MyAlg : public Gaudi::Algorithm {
// "InputTracks" is the property name, "/Event/Tracks" the location
DataObjectReadHandle<MyTrack::Container> m_in{ this, "InputTracks", "/Event/Tracks" };
DataObjectWriteHandle<MyTrack::Selection> m_out{ this, "OutputTracks", "/Event/SelectedTracks" };
...
};
|
What the declaration buys you:
the framework knows the inputs and outputs of the algorithm — this is what the scheduler uses to build the data flow (see The framework architecture);
read-only access is checked at compile time (a
ReadHandleonly givesconstaccess);collisions are detected at run time, trying to overwrite on existing location will fail
the store location is a
Gaudi::Propertymember of the component: users can redirect it from the job configuration, e.g.C.MyAlg(InputTracks="/Event/Sim/Tracks"). The third parameter in the declaration is only the default value.
Reading and writing:
1 2 3 4 5 6 7 | StatusCode execute( const EventContext& ) const override {
const auto* tracks = m_in.get(); // throws if the product is missing
const auto* maybe = m_in.getIfExists(); // returns nullptr if missing
...
m_out.put( std::make_unique<MyTrack::Selection>( ... ) );
return StatusCode::SUCCESS;
}
|
Ownership of the object passed to put is taken over by the store;
publish with std::unique_ptr and do not keep a pointer for later
modification.
In the functional framework the same handles are generated from the algorithm’s signature; only the locations are declared explicitly:
Transformer( name, pSvc,
{ "InputData", "MyTracks" }, // a DataObjectReadHandle<MyTracks>
{ "OutputData", "MyOutTracks" } )
5.3. Selections and ranges¶
Several handle-based conveniences exist to read containers:
a
DataObjectHandle<Gaudi::Range_<T::ConstVector>>gives a range over the content of a container in the store, which the functional transformers typically take as argument;the range read transparently adapts whether the store holds a full container or a
Selectionof it (seetransformer.cppinGaudiTestSuite/src/FunctionalAlgorithms— the same transformer accepts both).
5.4. Detector conditions¶
Conditions data (calibration, alignment, …) has a lifetime spanning
several events and is not stored in the event whiteboard. It is
published by dedicated condition services/loader algorithms and accessed
through handles declared with the condition data mode (see
GaudiKernel/DataHandle.h and the DataObjID family). Details are
framework-level; the essential rule is the same: declare the dependency,
do not look the data up.
5.5. Persistency¶
The persistency of event data is not part of the generic algorithm
interface any more: there is no “converter per data type” machinery to
extend as in the old guide. Reading and writing events is achieved with
dedicated, experiment-specific algorithms that extract data from the
transient store and hand it over to the I/O backend of choice (ROOT,
HDF5, …), or the other way around. The Gaudi repository ships an
example in RootCnv (a ROOT-based conversion service) and
GaudiTestSuite/options/ROOT_IO shows its usage.