Go to the documentation of this file.
16 #include <fmt/format.h>
18 #include <gsl/pointers>
25 auto getTypeName( std::string_view dependency ) {
26 auto unknownClassPos = dependency.find(
"UNKNOWN_CLASS:" );
27 return ( unknownClassPos != std::string::npos )
28 ? std::string( dependency.substr( unknownClassPos + std::string(
"UNKNOWN_CLASS:" ).length() ) )
29 :
std::string( dependency );
33 auto getNameFromLoc( std::string_view loc ) {
34 auto lastSlashPos = loc.find_last_of(
'/' );
35 return std::string{ lastSlashPos != loc.npos ? loc.substr( lastSlashPos + 1 ) : loc };
51 :
Algorithm(
n,
l ),
m_fileId( this,
"OutputFile",
"NTuple",
"Identifier for the TFile to write to." ) {}
59 if ( extraInputs.empty() ) {
60 error() <<
"No extra inputs locations specified. Please define extra inputs for the NTuple writer." <<
endmsg;
64 m_fileSvc = service<Gaudi::Interfaces::IFileSvc>(
"FileSvc" );
66 error() <<
"Failed to retrieve FileSvc." <<
endmsg;
72 error() <<
"Failed to retrieve TFile." <<
endmsg;
93 .
orThrow(
fmt::format(
"Failed to retrieve object for location '{}'. Ensure the location is correct and "
95 wrapper.getLocation() ),
100 std::scoped_lock lock{
m_mtx };
101 for ( std::size_t i = 0;
auto& wrapper :
m_branchWrappers ) { wrapper.setBranchData( pObjs[i++] ); }
111 if (
m_tree->Write() <= 0 ) {
112 error() <<
"Failed to write TTree to ROOT file." <<
endmsg;
116 info() <<
"TTree written to ROOT file. File closed." <<
endmsg;
124 for (
const auto& dep : extraInputs ) {
125 auto typeName = getTypeName( dep.className() );
126 auto branchName = getNameFromLoc( dep.key() );
135 std::unordered_set<std::string> classNames;
136 for (
auto& wrapper :
m_branchWrappers ) { classNames.insert( wrapper.getClassName() ); }
145 "Name of the TTree" };
159 # define BOOST_TEST_MODULE test_GenericNTupleWriter
160 # include <boost/test/unit_test.hpp>
168 virtual const std::list<IService*>&
getServices()
const override {
169 static std::list<IService*> dummyServices;
170 return dummyServices;
173 virtual bool existsService( std::string_view )
const override {
return false; }
180 virtual unsigned long addRef()
const override {
return 1; }
182 virtual unsigned long release()
const override {
return 1; }
186 virtual std::vector<std::string>
getInterfaceNames()
const override {
return {}; }
188 virtual void const*
i_cast(
const InterfaceID& )
const override {
return nullptr; }
190 virtual unsigned long refCount()
const override {
return 1; }
192 virtual unsigned long decRef()
const override {
return 1; }
196 BOOST_AUTO_TEST_CASE( testGetTypeName ) {
198 BOOST_CHECK_EQUAL( getTypeName(
"MyClass" ),
"MyClass" );
199 BOOST_CHECK_EQUAL( getTypeName(
"std::vector<double>" ),
"std::vector<double>" );
200 BOOST_CHECK_EQUAL( getTypeName(
"UNKNOWN_CLASS:MyCustomClass" ),
"MyCustomClass" );
203 BOOST_AUTO_TEST_CASE( testGetNameFromLoc ) {
205 BOOST_CHECK_EQUAL( getNameFromLoc(
"/Event/MyAlg/MyData" ),
"MyData" );
206 BOOST_CHECK_EQUAL( getNameFromLoc(
"MyAlg/MyData" ),
"MyData" );
207 BOOST_CHECK_EQUAL( getNameFromLoc(
"MyData" ),
"MyData" );
208 BOOST_CHECK_EQUAL( getNameFromLoc(
"" ),
"" );
212 BOOST_AUTO_TEST_CASE( testInit ) {
213 MockISvcLocator mockLocator;
217 BOOST_CHECK_EQUAL(
writer.name(),
"test_writer" );
221 BOOST_AUTO_TEST_CASE( testCreateBranches_EmptyDeps ) {
222 MockISvcLocator mockLocator;
230 BOOST_AUTO_TEST_CASE( testCreateBranches_InvalidType ) {
231 MockISvcLocator mockLocator;
232 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
234 writer.setTree( tree.get() );
240 return e.message() ==
"Cannot create branch loc for unknown class: InvalidType. Provide a dictionary please.";
245 BOOST_AUTO_TEST_CASE( testCreateBranches_BasicTypes ) {
246 MockISvcLocator mockLocator;
247 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
249 writer.setTree( tree.get() );
251 DataObjIDColl dependencies{ {
"int",
"loc1" }, {
"double",
"loc2" }, {
"std::string",
"loc3" } };
252 std::unordered_set<std::string> expectedTypes{
"int",
"double",
"std::string" };
253 writer.createBranches( dependencies );
256 BOOST_CHECK_EQUAL(
writer.getBranchWrappersSize(), expectedTypes.size() );
257 BOOST_CHECK( expectedTypes ==
writer.getBranchesClassNames() );
261 BOOST_AUTO_TEST_CASE( testCreateBranches_ROOTKnownTypes ) {
262 MockISvcLocator mockLocator;
263 auto tree = std::make_unique<TTree>(
"testTree",
"test tree" );
265 writer.setTree( tree.get() );
267 DataObjIDColl dependencies{ {
"std::vector<double>",
"vectorDoubleLoc" }, {
"TH1D",
"hist1DLoc" } };
268 std::unordered_set<std::string> expectedTypes{
"std::vector<double>",
"TH1D" };
269 writer.createBranches( dependencies );
272 BOOST_CHECK_EQUAL(
writer.getBranchWrappersSize(), expectedTypes.size() );
273 BOOST_CHECK( expectedTypes ==
writer.getBranchesClassNames() );
size_t getBranchWrappersSize() const
virtual const std::list< IService * > & getServices() const =0
Return the list of Services.
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
const StatusCode & orThrow(std::string_view message, std::string_view tag) const
Throw a GaudiException in case of failures.
const std::string & name() const override
The identifying name of the algorithm object.
SmartIF< IDataProviderSvc > & eventSvc() const
The standard event data service.
StatusCode initialize() override
the default (empty) implementation of IStateful::initialize() method
std::vector< Gaudi::details::BranchWrapper > m_branchWrappers
std::shared_ptr< TFile > m_file
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
virtual void const * i_cast(const InterfaceID &) const =0
virtual unsigned long addRef() const =0
Increment the reference count of Interface instance.
IDataProviderSvc * m_eventSvc
StatusCode finalize() override
StatusCode initialize() override
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
void createBranches(const DataObjIDColl &extraInputs)
Helper class to parse a string of format "type/name".
Gaudi::Property< std::string > m_fileId
Gaudi::Interfaces::IFileSvc * m_fileSvc
virtual StatusCode retrieveObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject)=0
Retrieve object identified by its directory entry.
Base class from which all concrete algorithm classes should be derived.
const ValueType & value() const
virtual const DataObjIDColl & extraInputDeps() const override
void setTree(TTree *tree)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
std::unordered_set< DataObjID, DataObjID_Hasher > DataObjIDColl
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
GenericWriter(const std::string &n, ISvcLocator *l)
StatusCode execute(const EventContext &) const override
Gaudi::Property< std::string > m_ntupleTname
StatusCode finalize() override
the default (empty) implementation of IStateful::finalize() method
constexpr static const auto SUCCESS
std::string typeName(const std::type_info &typ)
#define DECLARE_COMPONENT(type)
A Gaudi algorithm for writing data of any type from N locations in the event store to a TTree....
virtual std::vector< std::string > getInterfaceNames() const =0
Returns a vector of strings containing the names of all the implemented interfaces.
virtual std::shared_ptr< TFile > getFile(const std::string &identifier)=0
Get a shared pointer to a TFile based on an identifier.
Interface for a component that manages file access within Gaudi applications.
virtual unsigned long decRef() const =0
Decrement reference count and return the new reference count.
constexpr static const auto FAILURE
virtual unsigned long refCount() const =0
Current reference count.
virtual bool existsService(std::string_view name) const =0
Check the existence of a service given a service name.
virtual unsigned long release() const =0
Release Interface instance.
std::unordered_set< std::string > getBranchesClassNames() const