ATLAS Offline Software
OutputStreamData.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 
8 
9 //
10 // includes
11 //
12 
14 
16 #include <RootCoreUtils/Assert.h>
18 #include <TH1.h>
19 #include <TTree.h>
20 #include <tuple>//for std::ignore
21 
22 //
23 // method implementations
24 //
25 
26 namespace 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 
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 
106  testInvariant () const
107  {
108  RCU_INVARIANT (this != nullptr);
109  RCU_INVARIANT (m_writer != nullptr);
110  }
111 
112 
113 
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 
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 
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 
142  file () const noexcept
143  {
144  RCU_READ_INVARIANT (this);
145  TFile *result = m_writer->file();
146  RCU_PROVIDE (result != nullptr);
147  return result;
148  }
149 
150 
151 
153  close ()
154  {
155  RCU_CHANGE_INVARIANT (this);
156  saveOutput ();
157  m_writer->close ();
158  }
159 
160 
161 
163  finalFileName () const
164  {
165  RCU_READ_INVARIANT (this);
166  return m_writer->path ();
167  }
168 
169 
170 
172  saveOutput ()
173  {
174  RCU_CHANGE_INVARIANT (this);
175  TFile *const file {m_writer->file()};
176  RCU_ASSERT (file != nullptr);
177  for (std::unique_ptr<TObject>& object : m_output)
178  {
179  std::string name = object->GetName();
180  TDirectory *dir = makeDirectoryFor (name);
181  if (dir != file)
182  {
183  TNamed *named = dynamic_cast<TNamed*>(object.get());
184  if (named)
185  named->SetName (name.c_str());
186  }
187 
188  if (!RCU::SetDirectory (object.get(), dir))
189  {
190  dir->WriteObject (object.get(), name.c_str());
191  }
192  //release object which was consumed by SetDirectory or WriteObject
193  //placate cppcheck using std::ignore
194  std::ignore = object.release();
195  }
196  m_outputHistMap.clear ();
197  m_outputTreeMap.clear ();
198  m_output.clear ();
199  }
200 
201 
202 
204  addOutput (std::unique_ptr<TObject> outputObject)
205  {
206  RCU_CHANGE_INVARIANT (this);
207 
208  TTree *const tree = dynamic_cast<TTree*> (outputObject.get());
209  if (tree)
210  {
211  std::string name = tree->GetName();
212  std::string treeName = tree->GetName();
213 
214  TDirectory *dir = makeDirectoryFor (treeName);
215 
216  // if we are in a sub-directory we need to rename the tree
217  if (name != treeName)
218  tree->SetName (treeName.c_str());
219 
220  // pass ownership of the tree to the directory
221  tree->SetDirectory (dir);
222  outputObject.release();
223 
225 
226 
227  } else
228  {
229  TH1 *const hist = dynamic_cast<TH1*> (outputObject.get());
230 
231  m_outputHistMap[outputObject->GetName()] = outputObject.get();
232  m_output.emplace_back (std::move (outputObject));
233  if (hist)
234  hist->SetDirectory (nullptr);
235  }
236  }
237 
238 
239 
241  addClone (const TObject& prototypeObject)
242  {
243  // no invariant used
244 
245  // Do not change the user's "current directory" during any of the
246  // following...
247  DirectoryReset dirReset;
248 
249  // Make a clone of the object, and make sure we are already in
250  // the right directory if needed
251  std::string name = prototypeObject.GetName();
252  TDirectory *dir = makeDirectoryFor (name);
253  dir->cd();
254 
255  std::unique_ptr<TObject> clone {prototypeObject.Clone()};
256 
257  // Hold on to the pointer of the tree in our internal cache.
258  addOutput (std::move (clone));
259  }
260 
261 
262 
264  makeDirectoryFor (std::string& name)
265  {
266  RCU_CHANGE_INVARIANT (this);
267 
268  TDirectory *result = file();
269  std::string::size_type split = name.rfind ("/");
270  if (split == std::string::npos)
271  {
272  return result;
273  } else
274  {
275  const std::string dirname = name.substr (0, split);
276  name = name.substr (split + 1);
277  TDirectory *subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
278  if (!subdir)
279  {
280  result->mkdir (dirname.c_str());
281  subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
282  RCU_ASSERT (subdir != nullptr);
283  }
284  result = subdir;
285  RCU_ASSERT (result != nullptr);
286  return result;
287  }
288  }
289 
290 
291 
293  getOutputHist (const std::string& name) const noexcept
294  {
295  RCU_READ_INVARIANT (this);
296 
297  auto iter = m_outputHistMap.find (name);
298  return iter != m_outputHistMap.end() ? iter->second : nullptr;
299  }
300 
301 
302 
304  getOutputTree (const std::string& name) const noexcept
305  {
306  RCU_READ_INVARIANT (this);
307 
308  auto iter = m_outputTreeMap.find (name);
309  return iter != m_outputTreeMap.end() ? iter->second : nullptr;
310  }
311  }
312 }
EL::Detail::OutputStreamData::addOutput
void addOutput(std::unique_ptr< TObject > outputObject)
add the given output object to this stream
Definition: OutputStreamData.cxx:204
EL::Detail::OutputStreamData
all data needed to manage a given output stream
Definition: OutputStreamData.h:30
EL::Detail::OutputStreamData::file
TFile * file() const noexcept
the file we are writing to
Definition: OutputStreamData.cxx:142
EL::Detail::OutputStreamData::m_output
std::vector< std::unique_ptr< TObject > > m_output
the list of objects to write out at the end of job
Definition: OutputStreamData.h:170
EL::Detail::OutputStreamData::getOutputHist
TObject * getOutputHist(const std::string &name) const noexcept
get the output histogram with the given name, or nullptr if there is no histogam with such a name
Definition: OutputStreamData.cxx:293
m_dir
TDirectory & m_dir
The directory we need to return to.
Definition: OutputStreamData.cxx:41
get_generator_info.result
result
Definition: get_generator_info.py:21
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
EL::Detail::OutputStreamData::getOutputTree
TTree * getOutputTree(const std::string &name) const noexcept
get the output tree with the given name, or nullptr if there is no tree with such a name
Definition: OutputStreamData.cxx:304
RootUtils.h
make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Definition: SkimmingToolEXOT5.cxx:23
plotmaker.hist
hist
Definition: plotmaker.py:148
EL::Detail::OutputStreamData::addClone
void addClone(const TObject &prototypeObject)
add a clone of the given object to the output
Definition: OutputStreamData.cxx:241
tree
TChain * tree
Definition: tile_monitor.h:30
dirname
std::string dirname(std::string name)
Definition: utils.cxx:200
EL::Detail::OutputStreamData::close
void close()
close this file
Definition: OutputStreamData.cxx:153
EL::Detail::OutputStreamData::m_writer
std::unique_ptr< SH::DiskWriter > m_writer
the writer we use
Definition: OutputStreamData.h:166
Assert.h
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
python.Utilities.clone
clone
Definition: Utilities.py:134
m_file
std::unique_ptr< TFile > m_file
description: this is a custom writer for the old-school drivers that don't use an actual writer
Definition: OutputStreamData.cxx:52
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:58
RCU_PROVIDE
#define RCU_PROVIDE(x)
Definition: Assert.h:215
EL::Detail::OutputStreamData::m_outputTreeMap
std::unordered_map< std::string, TTree * > m_outputTreeMap
the output tree map
Definition: OutputStreamData.h:178
OutputStreamData.h
EL::Detail::OutputStreamData::finalFileName
std::string finalFileName() const
the final path of the file created
Definition: OutputStreamData.cxx:163
ParseInputs.gDirectory
gDirectory
Definition: Final2012/ParseInputs.py:133
m_path
std::string m_path
the path being used
Definition: OutputStreamData.cxx:88
file
TFile * file
Definition: tile_monitor.h:29
dumpFileToPlots.treeName
string treeName
Definition: dumpFileToPlots.py:20
EL
This module defines the arguments passed from the BATCH driver to the BATCH worker.
Definition: AlgorithmWorkerData.h:24
Preparation.mode
mode
Definition: Preparation.py:94
SH::DiskWriter
an interface that manages writing a single output file
Definition: DiskWriter.h:29
EL::Detail::OutputStreamData::testInvariant
void testInvariant() const
test the invariant of this object
Definition: OutputStreamData.cxx:106
RCU_INVARIANT
#define RCU_INVARIANT(x)
Definition: Assert.h:201
beamspotman.dir
string dir
Definition: beamspotman.py:623
StatusCode.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
xAOD::DiTauJetParameters::Detail
Detail
Definition: DiTauDefs.h:38
RCU::SetDirectory
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
EL::Detail::OutputStreamData::makeDirectoryFor
TDirectory * makeDirectoryFor(std::string &name)
make the directory for the object of the given name
Definition: OutputStreamData.cxx:264
RCU_REQUIRE2_SOFT
#define RCU_REQUIRE2_SOFT(x, y)
Definition: Assert.h:155
EL::Detail::OutputStreamData::m_outputHistMap
std::unordered_map< std::string, TObject * > m_outputHistMap
the output histogram map
Definition: OutputStreamData.h:174
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
RCU_CHANGE_INVARIANT
#define RCU_CHANGE_INVARIANT(x)
Definition: Assert.h:231
EL::Detail::OutputStreamData::saveOutput
void saveOutput()
write the list of output objects to disk and clear it
Definition: OutputStreamData.cxx:172
python.LumiCalcRecover.subdir
subdir
Definition: LumiCalcRecover.py:25
RCU_ASSERT
#define RCU_ASSERT(x)
Definition: Assert.h:222
RCU_READ_INVARIANT
#define RCU_READ_INVARIANT(x)
Definition: Assert.h:229
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
EL::Detail::OutputStreamData::OutputStreamData
OutputStreamData(const std::string &val_fileName, const std::string &mode)
open the given file and create an output stream for it
Definition: OutputStreamData.cxx:115
RCU_NEW_INVARIANT
#define RCU_NEW_INVARIANT(x)
Definition: Assert.h:233