![]() |
Project
|
Generate a processor spec for the RootTreeWriter utility. More...
#include <MakeRootTreeWriterSpec.h>
Classes | |
struct | AuxInputRoute |
struct | BranchDefinition |
struct | KeyExtractor |
unary helper functor to extract the input key from the InputSpec More... | |
struct | Preprocessor |
struct | StringAssignable |
helper for the constructor selection below More... | |
struct | StringAssignable< T, std::enable_if_t< std::is_same_v< std::decay_t< T >, char const * >||std::is_same_v< std::decay_t< T >, char * >||std::is_same_v< std::decay_t< T >, std::string > > > |
struct | TerminationCondition |
struct | TreeAttributes |
Public Types | |
enum struct | TerminationPolicy { Process , Workflow } |
using | WriterType = RootTreeWriter |
using | CustomClose = WriterType::CustomClose |
Public Member Functions | |
MakeRootTreeWriterSpec ()=delete | |
default constructor forbidden | |
template<typename... Args> | |
MakeRootTreeWriterSpec (const char *processName, Args &&... args) | |
DataProcessorSpec | operator() () |
Public Attributes | |
const std::map< std::string, TerminationPolicy > | TerminationPolicyMap |
Generate a processor spec for the RootTreeWriter utility.
A DPL processor is defined using o2::framework::DataProcessorSpec which holds the basic information for the processor, i.e. inputs, the algorithm, and outputs. In addition, the processor may support command line options.
The generator is configured with the process name and a list of branch definitions. Each branch definition holds the type of the data object to be extracted and stored, InputSpec to describe the input route, and branchname to describe output branch. Further optional arguments directly after the process name can change the behavior of spec options defaults.
A branch definition is always bound to a data type, the advanced version supports multiple branches for the same data type. See further down.
Processing spec is generated by invoking the class as functor;
const char*<\tt> is used as type. Data is written as a std::vector<char>
, this ensures separation on event basis as well as having binary data in parallel to ROOT objects in the same file, e.g. a binary data format from the reconstruction in parallel to MC labels.
--outfile
--output-dir
--treename
--nevents
--autosave
--terminate
In addition to that, a custom option can be added for every branch to configure the branch name, see below.
Default file name can be configured alone, tree name can only be specified after file name. The default number of events can be specified at arbitrary place between process name and branch configuration. The number of events triggering autosaving (by default - off) can be also specified in the constructor as an integer argument coming after (not necessarilly immidiately) the number or events. The process will signal to the DPL that it is ready for termination.
The configurable termination policy specifies what to signal to the DPL when the event count is reached. Currently option 'process' terminates only the process and 'workflow' all the workflow processes. The default option of this command line argument can be chosen by using either TerminationPolicy::Workflow or TerminationPolicy::Process. without custom configuration, the default argument is 'process'.
Independently of the event counter, custom termination evaluation can be added using MakeRootTreeWriterSpec::TerminationCondition. The two available actions determine whether to do the processing of an input object or skip it. The two types of evaluators are checked before or after extraction of an object from the input.
WorkflowSpec specs;
specs.emplace_back(MakeRootTreeWriterSpec<Types...>
(
"process_name",
"default_file_name",
"default_tree_name",
1, // default number of events
MakeRootTreeWriterSpec::TerminationPolicy::Workflow, // terminate the workflow
MakeRootTreeWriterSpec::BranchDefinition<Type>{ InputSpec{ ... }, "branchname" },
... // further input and branch config
)() // invocation of operator()
);
// skipping defaults
specs.emplace_back(MakeRootTreeWriterSpec<Types...>
(
"process_name",
MakeRootTreeWriterSpec::BranchDefinition<Type>{ InputSpec{ ... }, "branchname" },
... // further input and branch config
)() // invocation of operator()
);
// only file name default
specs.emplace_back(MakeRootTreeWriterSpec<Types...>
(
"process_name",
"default_file_name",
MakeRootTreeWriterSpec::BranchDefinition<Type>{ InputSpec{ ... }, "branchname" },
... // further input and branch config
)() // invocation of operator()
);
The option key is specified as part of the branch definition, a key-value option is added with branchname as default value MakeRootTreeWriterSpec::BranchDefinition<Type>{ InputSpec{ ... }, "branchname", "optionkey" }
In order to write to multiple branches, the definition can be extended by
- number n of branches controlled by definition
- callback to calculate an index in the range [0,n-1] from the DataRef argument(s): o2::framework::DataRef const& result: size_t index, data set is skipped if ~(size_t)0
- callback to return the branch name for an index argument(s): std::string basename, size_t index result: std::string with branchname
Multiple inputs for the same data type can be handled by the same branch definition by specifying a vector of InputSpecs instead of a single InputSpec. The number of branches has to be equal or larger than the size of the vector. template <typename T>
using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>;
// the callback to retrieve index from DataHeader
auto getIndex = [](o2::framework::DataRef const& ref) {
using DataHeader = o2::header::DataHeader;
auto const* dataHeader = o2::framework::DataRefUtils::getHeader<DataHeader*>(ref);
return dataHeader->subSpecification;
};
// the callback for the branch name
auto getName = [](std::string base, size_t index) {
return base + " " + std::to_string(index);
};
// assuming 4 inputs distinguished by DataHeader sub specification
std::vector<InputSpec> inputs{ {"...", "...", 0}, ... , {"...", "...", 3} };
// advanced branch definition
auto def = BranchDefinition<DataType>{ inputs,
"branchname",
4,
getIndex,
getName };
A single input can also be distributed to multiple branches if the getIndex callback calculates the index from another piece of information in the header stack.
auto checkProcessing = [](o2::framework::DataRef const& ref, bool& isReady) {
// decide on the DataRef whether to terminate or not
isReady = true;
// return true if the normal processing in this cycle should be carried out
// return false to skip
return false;
};
auto checkReady = [](o2::framework::DataRef const& ref) {
// decide on the DataRef whether to terminate or not
return true;
};
Now add MakeRootTreeWriterSpec::TerminationCondition{ checkReady } to the constructor arguments. Only one of the callback types can be used with TerminationCondition.
Definition at line 195 of file MakeRootTreeWriterSpec.h.
Definition at line 321 of file MakeRootTreeWriterSpec.h.
Definition at line 198 of file MakeRootTreeWriterSpec.h.
|
strong |
Enumerator | |
---|---|
Process | |
Workflow |
Definition at line 199 of file MakeRootTreeWriterSpec.h.
|
delete |
default constructor forbidden
|
inline |
Definition at line 327 of file MakeRootTreeWriterSpec.h.
|
inline |
Definition at line 332 of file MakeRootTreeWriterSpec.h.
const std::map<std::string, TerminationPolicy> o2::framework::MakeRootTreeWriterSpec::TerminationPolicyMap |
Definition at line 203 of file MakeRootTreeWriterSpec.h.