ATLAS Offline Software
Loading...
Searching...
No Matches
RNtupleTreeMakerAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local include(s):
7
8// ROOT include(s):
9#include <TFile.h>
10#include <TROOT.h>
11
12// Gaudi/EventLoop include(s):
13#ifdef XAOD_STANDALONE
14#include "EventLoop/Worker.h"
15#else
16#include "Gaudi/Parsers/CommonParsers.h"
17#endif
18
19#ifndef XAOD_STANDALONE
20namespace
21{
22
23TFile *fileForStream(const std::vector<std::string> &outputs,
24 const std::string &stream)
25{
26 std::string fileName;
27 for (const std::string &entry : outputs) {
28 const auto pos = entry.find_first_of(" \t");
29 if (entry.substr(0, pos) == stream) {
30 static const std::regex re(R"((?:DATA)?FILE\s*=\s*['"]([^'"]+)['"])", std::regex::icase);
31 std::smatch m;
32 if (std::regex_search(entry, m, re)) {
33 fileName = m[1].str();
34 break;
35 }
36 return nullptr;
37 }
38 }
39
40 if (fileName.empty()) {
41 return nullptr;
42 }
43
44 for (TObject *file : *gROOT->GetListOfFiles()) {
45 if (file == nullptr) {
46 continue;
47 }
48
49 if (file->GetName() == fileName) {
50 return dynamic_cast<TFile*>(file);
51 }
52 }
53
54 return nullptr;
55}
56
57}
58#endif
59
60namespace CP {
61
63 if( m_branches.empty() ) {
64 ATH_MSG_ERROR( "No branches set up for writing" );
65 return StatusCode::FAILURE;
66 }
67 ATH_CHECK( m_systematicsService.retrieve() );
68 return StatusCode::SUCCESS;
69 }
70
71 StatusCode RNtupleTreeMakerAlg::execute(const EventContext& /*ctx*/) {
72 if( ! m_isInitialized ) {
73 m_model = ROOT::RNTupleModel::Create();
74 if ( !m_model ) {
75 ATH_MSG_ERROR( "Failed to create RNTupleModel" );
76 return StatusCode::FAILURE;
77 }
78
80
81 TFile* outputFile = nullptr;
82#ifdef XAOD_STANDALONE
83 if( wk() ) {
84 outputFile = wk()->getOutputFile( m_outputStreamName.value() );
85 } else {
86 ATH_MSG_ERROR( "Worker not available in standalone mode" );
87 return StatusCode::FAILURE;
88 }
89#else
90 // Get the output file from THistSvc until we can use it directly
91 SmartIF<IProperty> prop{histSvc().get()};
92 std::vector<std::string> outputs;
93 ATH_CHECK(Gaudi::Parsers::parse(outputs, prop->getProperty("Output").toString()));
94 outputFile = fileForStream(outputs, m_outputStreamName.value());
95 if (outputFile == nullptr) {
96 ATH_MSG_ERROR( "Could not find TFile for stream: " << m_outputStreamName.value() );
97 return StatusCode::FAILURE;
98 }
99#endif
100
101 if( !outputFile ) {
102 ATH_MSG_ERROR( "Could not retrieve file for stream: " << m_outputStreamName.value() );
103 return StatusCode::FAILURE;
104 }
105
106 try {
107 // ROOT requires the zipped target to not exceed the unzipped maximum
108 // at every step, so set the zipped target first
109 ROOT::RNTupleWriteOptions options;
110 if( m_approxZippedClusterSize.value() > 0 ) {
111 options.SetApproxZippedClusterSize( m_approxZippedClusterSize.value() );
112 }
113 if( m_maxUnzippedClusterSize.value() > 0 ) {
114 if ( options.GetApproxZippedClusterSize() > m_maxUnzippedClusterSize.value() ) {
115 options.SetApproxZippedClusterSize( m_maxUnzippedClusterSize.value() );
116 }
117 options.SetMaxUnzippedClusterSize( m_maxUnzippedClusterSize.value() );
118 }
119 m_writer = ROOT::RNTupleWriter::Append( std::move(m_model), m_modelName.value(), *outputFile, options );
120 } catch( const std::exception& e ) {
121 ATH_MSG_ERROR( "Failed to create RNTupleWriter: " << e.what() );
122 return StatusCode::FAILURE;
123 }
124
125 m_isInitialized = true;
126 }
127
128 ATH_CHECK( m_processorList.process( *(evtStore()) ) );
129
130 if ( m_writer ) {
131 m_writer->Fill();
132 }
133
134 return StatusCode::SUCCESS;
135 }
136
138 m_writer.reset();
139 return StatusCode::SUCCESS;
140 }
141
143 std::unordered_set<std::string> nonContainerSet( m_nonContainers.begin(), m_nonContainers.end() );
144 ATH_CHECK( m_processorList.setupTree( m_branches, std::move(nonContainerSet), *m_systematicsService, *m_model ) );
145 return StatusCode::SUCCESS;
146 }
147
148
149
150 // Removed old ContainerProcessor/ElementProcessor implementations as they are now in FieldHelpers
151} // namespace CP
const std::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x,...)
ServiceHandle< StoreGateSvc > & evtStore()
const ServiceHandle< ITHistSvc > & histSvc() const
The standard THistSvc (for writing histograms and TTrees and more to a root file) Returns (kind of) a...
Gaudi::Property< std::vector< std::string > > m_nonContainers
Gaudi::Property< std::vector< std::string > > m_branches
Gaudi::Property< std::string > m_outputStreamName
StatusCode setupTree()
Function setting up the internal data structures on the first event.
Gaudi::Property< std::string > m_modelName
CP::RNtupleFieldHelpers::ProcessorList m_processorList
std::unique_ptr< ROOT::RNTupleWriter > m_writer
virtual StatusCode initialize() override
Function executed during algorithm initialization.
ServiceHandle< ISystematicsSvc > m_systematicsService
Service handle for systematics.
Gaudi::Property< std::size_t > m_maxUnzippedClusterSize
virtual StatusCode finalize() override
Function executed during algo finalization.
std::unique_ptr< ROOT::RNTupleModel > m_model
Gaudi::Property< std::size_t > m_approxZippedClusterSize
virtual::StatusCode execute()
execute this algorithm
Select isolated Photons, Electrons and Muons.
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
TFile * file