ATLAS Offline Software
Loading...
Searching...
No Matches
OutputStreamData.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8
9//
10// includes
11//
12
14
18#include <TH1.h>
19#include <TTree.h>
20#include <tuple>//for std::ignore
21
22//
23// method implementations
24//
25
26namespace EL
27{
28 namespace Detail
29 {
30 namespace
31 {
33 class DirectoryReset {
34 public:
36 DirectoryReset() : m_dir( *gDirectory ) {}
38 ~DirectoryReset() { m_dir.cd(); }
39 private:
41 TDirectory& m_dir;
42 };
43
44
45
46 struct MyWriter : public SH::DiskWriter
47 {
50
51 public:
52 std::unique_ptr<TFile> m_file;
53
54 explicit MyWriter (std::unique_ptr<TFile> val_file)
55 : m_file (std::move (val_file))
56 {
57 if (m_file == nullptr)
58 throw std::runtime_error ("encountered null pointer for output file");
59 m_path = m_file->GetName();
60 }
61
62 ~MyWriter ()
63 {
64 if (m_file != 0)
65 close();
66 }
67 //cppcheck-suppress returnByReference
68 std::string getPath () const
69 {
70 return m_path;
71 }
72
73 TFile *getFile ()
74 {
75 RCU_REQUIRE2_SOFT (m_file != 0, "file already closed");
76 return m_file.get();
77 }
78
79 void doClose ()
80 {
81 RCU_REQUIRE2_SOFT (m_file != 0, "file already closed");
82 m_file->Write ();
83 m_file->Close ();
84 m_file = 0;
85 }
87 private:
88 std::string m_path;
89 };
90
91
92
94 std::unique_ptr<TFile> checkedOpenFile (const std::string& path, const std::string& mode)
95 {
96 std::unique_ptr<TFile> result (TFile::Open (path.c_str(), mode.c_str()));
97 if (result == nullptr)
98 throw std::runtime_error ("failed to open file " + path + " with mode " + mode);
99 return result;
100 }
101 }
102
103
104
105 void OutputStreamData ::
106 testInvariant () const
107 {
108 RCU_INVARIANT (this != nullptr);
109 RCU_INVARIANT (m_writer != nullptr);
110 }
111
112
113
114 OutputStreamData ::
115 OutputStreamData (const std::string& val_fileName, const std::string& mode)
116 : OutputStreamData (checkedOpenFile (val_fileName, mode))
117 {
118 // no invariant used
119 }
120
121
122
123 OutputStreamData ::
124 OutputStreamData (std::unique_ptr<TFile> file)
125 : OutputStreamData (std::make_unique<MyWriter> (std::move (file)))
126 {
127 // no invariant used
128 }
129
130
131
132 OutputStreamData ::
133 OutputStreamData (std::unique_ptr<SH::DiskWriter> val_writer)
134 : m_writer (std::move (val_writer))
135 {
136 RCU_NEW_INVARIANT (this);
137 }
138
139
140
141 const std::string& OutputStreamData ::
142 mainStreamName () const noexcept
143 {
144 RCU_READ_INVARIANT (this);
145 return m_mainStreamName;
146 }
147
148
149
150 void OutputStreamData ::
151 setMainStreamName (const std::string& val_mainStreamName)
152 {
154 if (!m_mainStreamName.empty())
155 throw std::runtime_error ("main stream name already set");
156 m_mainStreamName = val_mainStreamName;
157 }
158
159
160
161 TFile *OutputStreamData ::
162 file () const noexcept
163 {
164 RCU_READ_INVARIANT (this);
165 TFile *result = m_writer->file();
166 RCU_PROVIDE (result != nullptr);
167 return result;
168 }
169
170
171
172 void OutputStreamData ::
173 close ()
174 {
176 saveOutput ();
177 m_writer->close ();
178 }
179
180
181
182 std::string OutputStreamData ::
183 finalFileName () const
184 {
185 RCU_READ_INVARIANT (this);
186 return m_writer->path ();
187 }
188
189
190
191 void OutputStreamData ::
192 saveOutput ()
193 {
195 TFile *const file {m_writer->file()};
196 RCU_ASSERT (file != nullptr);
197 for (std::unique_ptr<TObject>& object : m_output)
198 {
199 std::string name = object->GetName();
200 TDirectory *dir = makeDirectoryFor (name);
201 if (dir != file)
202 {
203 TNamed *named = dynamic_cast<TNamed*>(object.get());
204 if (named)
205 named->SetName (name.c_str());
206 }
207
208 if (!RCU::SetDirectory (object.get(), dir))
209 {
210 dir->WriteObject (object.get(), name.c_str());
211 }
212 //release object which was consumed by SetDirectory or WriteObject
213 //placate cppcheck using std::ignore
214 std::ignore = object.release();
215 }
216 m_outputHistMap.clear ();
217 m_outputTreeMap.clear ();
218 m_output.clear ();
219 }
220
221
222
223 void OutputStreamData ::
224 addOutput (std::unique_ptr<TObject> outputObject)
225 {
227
228 TTree *const tree = dynamic_cast<TTree*> (outputObject.get());
229 if (tree)
230 {
231 std::string name = tree->GetName();
232 std::string treeName = tree->GetName();
233
234 TDirectory *dir = makeDirectoryFor (treeName);
235
236 // if we are in a sub-directory we need to rename the tree
237 if (name != treeName)
238 tree->SetName (treeName.c_str());
239
240 // pass ownership of the tree to the directory
241 tree->SetDirectory (dir);
242 outputObject.release();
243
244 m_outputTreeMap[name] = tree;
245
246
247 } else
248 {
249 TH1 *const hist = dynamic_cast<TH1*> (outputObject.get());
250
251 m_outputHistMap[outputObject->GetName()] = outputObject.get();
252 m_output.emplace_back (std::move (outputObject));
253 if (hist)
254 hist->SetDirectory (nullptr);
255 }
256 }
257
258
259
260 void OutputStreamData ::
261 addClone (const TObject& prototypeObject)
262 {
263 // no invariant used
264
265 // Do not change the user's "current directory" during any of the
266 // following...
267 DirectoryReset dirReset;
268
269 // Make a clone of the object, and make sure we are already in
270 // the right directory if needed
271 std::string name = prototypeObject.GetName();
272 TDirectory *dir = makeDirectoryFor (name);
273 dir->cd();
274
275 std::unique_ptr<TObject> clone {prototypeObject.Clone()};
276
277 // Hold on to the pointer of the tree in our internal cache.
278 addOutput (std::move (clone));
279 }
280
281
282
283 TDirectory *OutputStreamData ::
284 makeDirectoryFor (std::string& name)
285 {
287
288 TDirectory *result = file();
289 std::string::size_type split = name.rfind ("/");
290 if (split == std::string::npos)
291 {
292 return result;
293 } else
294 {
295 const std::string dirname = name.substr (0, split);
296 name = name.substr (split + 1);
297 TDirectory *subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
298 if (!subdir)
299 {
300 result->mkdir (dirname.c_str());
301 subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
302 RCU_ASSERT (subdir != nullptr);
303 }
304 result = subdir;
305 RCU_ASSERT (result != nullptr);
306 return result;
307 }
308 }
309
310
311
312 TObject *OutputStreamData ::
313 getOutputHist (const std::string& name) const noexcept
314 {
315 RCU_READ_INVARIANT (this);
316
317 auto iter = m_outputHistMap.find (name);
318 return iter != m_outputHistMap.end() ? iter->second : nullptr;
319 }
320
321
322
323 TTree *OutputStreamData ::
324 getOutputTree (const std::string& name) const noexcept
325 {
326 RCU_READ_INVARIANT (this);
327
328 auto iter = m_outputTreeMap.find (name);
329 return iter != m_outputTreeMap.end() ? iter->second : nullptr;
330 }
331 }
332}
#define RCU_INVARIANT(x)
Definition Assert.h:201
#define RCU_ASSERT(x)
Definition Assert.h:222
#define RCU_CHANGE_INVARIANT(x)
Definition Assert.h:231
#define RCU_REQUIRE2_SOFT(x, y)
Definition Assert.h:155
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:233
#define RCU_PROVIDE(x)
Definition Assert.h:215
#define RCU_READ_INVARIANT(x)
Definition Assert.h:229
std::unordered_map< std::string, TObject * > m_outputHistMap
the output histogram map
TFile * file() const noexcept
the file we are writing to
TDirectory * makeDirectoryFor(std::string &name)
make the directory for the object of the given name
OutputStreamData(const std::string &val_fileName, const std::string &mode)
open the given file and create an output stream for it
void saveOutput()
write the list of output objects to disk and clear it
void addOutput(std::unique_ptr< TObject > outputObject)
add the given output object to this stream
std::vector< std::unique_ptr< TObject > > m_output
the list of objects to write out at the end of job
std::string m_mainStreamName
the name of the main stream
std::unique_ptr< SH::DiskWriter > m_writer
the writer we use
std::unordered_map< std::string, TTree * > m_outputTreeMap
the output tree map
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
This module defines the arguments passed from the BATCH driver to the BATCH worker.
bool SetDirectory(TObject *object, TDirectory *directory)
effects: set the directory this object is associated with returns: whether the object type actively k...
Definition RootUtils.cxx:28
path
python interpreter configuration --------------------------------------—
Definition athena.py:128
STL namespace.
TChain * tree
TFile * file
std::string dirname(std::string name)
Definition utils.cxx:200