ATLAS Offline Software
FPGATrackSimOutputHeaderTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
8 
9 FPGATrackSimOutputHeaderTool::FPGATrackSimOutputHeaderTool(std::string const & algname, std::string const & name, IInterface const * ifc) :
10  AthAlgTool(algname,name,ifc) {}
11 
12 
13 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15 {
16  // close old file (I don't think we delete the pointer. Does ROOT handle that?)
17  if (m_infile && m_infile->IsOpen()) m_infile->Close();
18 
19  // open new file
20  ATH_MSG_DEBUG ("Opening file " << path.c_str() << " in " << m_rwoption.value() << " mode.");
21  m_infile = TFile::Open(path.c_str(), m_rwoption.value().c_str());
22 
23  if (!m_infile) {
24  ATH_MSG_FATAL("Could not open input file: " << path);
25  return StatusCode::FAILURE;
26  }
27 
28  if (m_rwoption.value() == std::string("READ")) {
29  // get the tree
30  m_EventTree = (TTree*) m_infile->Get(m_treeName.value().c_str());
31  if (!m_EventTree || m_EventTree->GetEntries() == -1) {
32  ATH_MSG_FATAL ("Input file: " << m_inpath.value() << " has no entries");
33  return StatusCode::FAILURE;
34  }
35 
36  ATH_MSG_INFO ("Input file: " << path << " has " << m_EventTree->GetEntries() << " event entries.");
37  }
38 
39  m_infile->cd();
40  m_event = 0;
41  return StatusCode::SUCCESS;
42 }
43 
44 // Since now the list of branches to read gets configured by algorithms, we can't do this in initialize().
45 // We could use properties to pass the branch names to this tool, but the algorithms would need to know those
46 // names too, so it may make more sense to store them as properties on individual algorithms.
47 
48 // Also... the properties would have to be a vector because we can have an arbitrary number of input and output headers.
49 // Perhaps we don't actually *need* an arbitrary number of input and output headers but I think it's best to allow for it.
50 
52 
53  // Don't do anything
54  if (m_rwoption.value() != std::string("READ")) {
55  ATH_MSG_FATAL("Called configureReadBranches() when ROOT file was not opened in READ mode.");
56  return StatusCode::FAILURE;
57  }
58 
59  // In read mode, we want to make sure the configured branches are actually available.
60  // Configuration is via a function call (to allow different algorithms to set up different numbers of branches).
61  for (unsigned i = 0; i < m_branchNameIns.size(); i++) {
62  std::string branchName = m_branchNameIns.at(i);
63  if (!m_EventTree->GetListOfBranches()->FindObject(branchName.c_str())) {
64  ATH_MSG_FATAL("Configured input branch: " << branchName << " not found!");
65  return StatusCode::FAILURE;
66  }
67  TBranch *branchIn = m_EventTree->GetBranch(branchName.c_str());
68  branchIn->SetAddress(&(m_eventInputHeaders.at(i)));
69  m_EventTree->SetBranchStatus(branchName.c_str(), 1);
70  }
71 
72  // Do the same thing for the output branches. In fact we could maybe combine these loops by making a function.
73  for (unsigned i = 0; i < m_branchNameOuts.size(); i++) {
74  std::string branchName = m_branchNameOuts.at(i);
75  if (!m_EventTree->GetListOfBranches()->FindObject(branchName.c_str())) {
76  ATH_MSG_FATAL("Configured output branch: " << branchName << " not found!");
77  return StatusCode::FAILURE;
78  }
79  TBranch *branchIn = m_EventTree->GetBranch(branchName.c_str());
80  branchIn->SetAddress(&(m_eventOutputHeaders.at(i)));
81  m_EventTree->SetBranchStatus(branchName.c_str(), 1);
82  }
83 
84  return StatusCode::SUCCESS;
85 }
86 
87 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
89 {
90 
91  ATH_CHECK(m_tHistSvc.retrieve());
92 
93  if( m_rwoption.value()!=std::string("HEADER"))
94  {
95  if (m_inpath.value().empty())
96  {
97  ATH_MSG_ERROR("Empty input file list");
98  return StatusCode::FAILURE;
99  }
100  ATH_CHECK(openFile(m_inpath.value().front()));
101  }
102 
103  if (m_rwoption.value() == std::string("READ")) {
104  ATH_MSG_DEBUG ("Initialized in READ MODE");
105  } else if (m_rwoption.value()==std::string("RECREATE") || m_rwoption.value()==std::string("HEADER")) {
106 
107  // branches are NO LONGER created here, the user needs to do this.
108  m_EventTree = new TTree(m_treeName.value().c_str(), "data");
109 
110  // For HEADER-- use THistSvc explicitly to set things up.
111  if (m_rwoption.value() == std::string("HEADER")) {
112  ATH_CHECK(m_tHistSvc->regTree(Form("/FPGATRACKSIMOUTPUT/%s", m_treeName.value().c_str()), m_EventTree));
113  }
114 
115  } else {
116  ATH_MSG_ERROR ("RWstatus = " << m_rwoption.value() << " is not allowed!");
117  return StatusCode::FAILURE;
118  }
119 
120  m_event = 0; // in file
121  m_totevent = 0; // total counter
122  return StatusCode::SUCCESS;
123 }
124 
125 // Create a new input or output branch and return a pointer to the header object so code can write to it.
126 // These functions work for both reading and writing.
130  m_branchNameIns.push_back(branchName);
131  if (write) {
132  m_EventTree->Branch(branchName.c_str(), "FPGATrackSimLogicalEventInputHeader", inputHeader);
133  }
134  return inputHeader;
135 }
136 
140  m_branchNameOuts.push_back(branchName);
141  if (write) {
142  m_EventTree->Branch(branchName.c_str(), "FPGATrackSimLogicalEventOutputHeader", outputHeader);
143  }
144  return outputHeader;
145 }
146 
147 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
149 {
150  ATH_MSG_INFO ("finalize: closing files");
151 
152  if (m_rwoption.value() == std::string("RECREATE")) {
153  ATH_MSG_INFO ("Contains " << m_EventTree->GetEntries() << " entries, over " << m_event << " events run");
154  // close the output files, but check that it exists (for athenaMP)
155  m_infile->Write();
156  }
157 
158  if (m_rwoption.value() != std::string("HEADER")) {
159  m_infile->Close();
160  }
161 
162  // deleting pointers
163  for (auto* header : m_eventInputHeaders) delete header;
164  for (auto* header : m_eventOutputHeaders) delete header;
165 
166  return StatusCode::SUCCESS;
167 }
168 
169 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
170 // This version of writeData assumes that the header objects were created using addInputBranch and addOutputBranch
171 // and so don't need to be passed back to the tool.
173 
174  if (m_rwoption.value() == std::string("READ")) {
175  ATH_MSG_WARNING ("Asked to write file in READ mode");
176  return StatusCode::SUCCESS;
177  }
178 
179  ATH_MSG_DEBUG ("Writing data in TTree");
180 
181  m_EventTree->Fill();
182 
183  // Reset any input headers that we wrote out (with debugging prints).
184  for (unsigned i = 0; i < m_eventInputHeaders.size(); i++) {
185  ATH_MSG_DEBUG("Wrote event " << m_event << " in input header (" << m_branchNameIns.at(i) << ") event " << m_eventInputHeaders.at(i)->event());
186  m_eventInputHeaders.at(i)->reset();
187  }
188 
189  // Reset any output headers that we wrote out (With debugging prints).
190  for (unsigned i = 0; i < m_eventOutputHeaders.size(); i++) {
191  ATH_MSG_DEBUG("Wrote event " << m_event << " in output header (" << m_branchNameOuts.at(i) << ")");
192  ATH_MSG_DEBUG("n.roads_1st = " << m_eventOutputHeaders.at(i)->nFPGATrackSimRoads_1st());
193  ATH_MSG_DEBUG("n.roads_2nd = " << m_eventOutputHeaders.at(i)->nFPGATrackSimRoads_2nd());
194  ATH_MSG_DEBUG("n.tracks_1st = " << m_eventOutputHeaders.at(i)->nFPGATrackSimTracks_1st());
195  ATH_MSG_DEBUG("n.tracks_2nd = " << m_eventOutputHeaders.at(i)->nFPGATrackSimTracks_2nd());
196  m_eventOutputHeaders.at(i)->reset();
197  }
198 
199  // Only return FAILURe if there were no input AND output headers (i.e. something is misconfigured).
200  if (m_eventInputHeaders.size() == 0 and m_eventOutputHeaders.size() == 0) {
201  ATH_MSG_ERROR("Tried to fill output ROOT file with no configured input or output headers.");
202  return StatusCode::FAILURE;
203  }
204 
205  m_event++;
206 
207  return StatusCode::SUCCESS;
208 }
209 
210 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
211 // Since the branches are now created using the same set of functions the user already has a pointer to the object.
212 // So in this function we just need to reset those objects, test last, and... call GetEntry I think.
214 {
215  if (m_rwoption.value() != std::string("READ")) {
216  ATH_MSG_WARNING ("Asked to read file that is not in READ mode");
217  return StatusCode::SUCCESS;
218  }
219 
220  for (auto* header : m_eventInputHeaders) {
221  header->reset();
222  }
223 
224  for (auto* header : m_eventOutputHeaders) {
225  header->reset();
226  }
227 
228  ATH_MSG_DEBUG ("Asked Event " << m_event << " in this file; current total is " << m_totevent);
229  last = false;
230  if (m_event >= m_EventTree->GetEntries()) {
231  if (++m_file < m_inpath.value().size()) {
232  ATH_CHECK(openFile(m_inpath.value().at(m_file)));
233  // If opening a new file we need to update the branch addresses.
235  }
236  else {
237  last = true;
238  return StatusCode::SUCCESS;
239  }
240  }
241 
242  // Read the objects. I removed some of the debug messages here, they could be readded.
243  for (const std::string& branchName : m_branchNameIns) {
244  int statIn = m_EventTree->GetBranch(branchName.c_str())->GetEntry(m_event);
245  if (statIn <= 0) ATH_MSG_WARNING("Error in reading from branch " << branchName);
246  }
247 
248  for (const std::string& branchName : m_branchNameOuts) {
249  int statOut = m_EventTree->GetBranch(branchName.c_str())->GetEntry(m_event);
250  if (statOut <= 0) ATH_MSG_WARNING("Error in reading from branch " << branchName);
251  }
252 
253  m_event++;
254  m_totevent++;
255 
256 
257  return StatusCode::SUCCESS;
258 }
259 
FPGATrackSimOutputHeaderTool::m_tHistSvc
ServiceHandle< ITHistSvc > m_tHistSvc
Definition: FPGATrackSimOutputHeaderTool.h:70
FPGATrackSimOutputHeaderTool::readData
StatusCode readData(bool &last)
Definition: FPGATrackSimOutputHeaderTool.cxx:213
FPGATrackSimOutputHeaderTool::m_branchNameOuts
std::vector< std::string > m_branchNameOuts
Definition: FPGATrackSimOutputHeaderTool.h:82
getMenu.algname
algname
Definition: getMenu.py:54
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
FPGATrackSimLogicalEventInputHeader
Definition: FPGATrackSimLogicalEventInputHeader.h:21
header
Definition: hcg.cxx:526
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
FPGATrackSimOutputHeaderTool::openFile
StatusCode openFile(std::string const &path)
Definition: FPGATrackSimOutputHeaderTool.cxx:14
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FPGATrackSimOutputHeaderTool::finalize
virtual StatusCode finalize() override
Definition: FPGATrackSimOutputHeaderTool.cxx:148
FPGATrackSimOutputHeaderTool::m_branchNameIns
std::vector< std::string > m_branchNameIns
Definition: FPGATrackSimOutputHeaderTool.h:81
FPGATrackSimOutputHeaderTool::m_file
std::atomic< unsigned > m_file
Definition: FPGATrackSimOutputHeaderTool.h:75
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
FPGATrackSimOutputHeaderTool::configureReadBranches
StatusCode configureReadBranches()
Definition: FPGATrackSimOutputHeaderTool.cxx:51
lumiFormat.i
int i
Definition: lumiFormat.py:85
FPGATrackSimOutputHeaderTool::m_rwoption
Gaudi::Property< std::string > m_rwoption
Definition: FPGATrackSimOutputHeaderTool.h:64
FPGATrackSimLogicalEventOutputHeader.h
FPGATrackSimOutputHeaderTool::addInputBranch
FPGATrackSimLogicalEventInputHeader * addInputBranch(const std::string &branchName, bool write=true)
Definition: FPGATrackSimOutputHeaderTool.cxx:127
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
FPGATrackSimOutputHeaderTool::addOutputBranch
FPGATrackSimLogicalEventOutputHeader * addOutputBranch(const std::string &branchName, bool write=true)
Definition: FPGATrackSimOutputHeaderTool.cxx:137
FPGATrackSimOutputHeaderTool::m_infile
TFile * m_infile
Definition: FPGATrackSimOutputHeaderTool.h:84
FPGATrackSimOutputHeaderTool::m_EventTree
TTree * m_EventTree
Definition: FPGATrackSimOutputHeaderTool.h:85
FPGATrackSimOutputHeaderTool::m_treeName
Gaudi::Property< std::string > m_treeName
Definition: FPGATrackSimOutputHeaderTool.h:67
python.ByteStreamConfig.write
def write
Definition: Event/ByteStreamCnvSvc/python/ByteStreamConfig.py:247
FPGATrackSimOutputHeaderTool::m_eventInputHeaders
std::vector< FPGATrackSimLogicalEventInputHeader * > m_eventInputHeaders
Definition: FPGATrackSimOutputHeaderTool.h:78
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
FPGATrackSimOutputHeaderTool::m_inpath
Gaudi::Property< std::vector< std::string > > m_inpath
Definition: FPGATrackSimOutputHeaderTool.h:60
FPGATrackSimOutputHeaderTool::m_event
std::atomic< unsigned > m_event
Definition: FPGATrackSimOutputHeaderTool.h:73
FPGATrackSimOutputHeaderTool.h
FPGATrackSimOutputHeaderTool::FPGATrackSimOutputHeaderTool
FPGATrackSimOutputHeaderTool(const std::string &, const std::string &, const IInterface *)
Definition: FPGATrackSimOutputHeaderTool.cxx:9
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
FPGATrackSimOutputHeaderTool::m_totevent
std::atomic< unsigned > m_totevent
Definition: FPGATrackSimOutputHeaderTool.h:74
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
FPGATrackSimOutputHeaderTool::writeData
StatusCode writeData()
Definition: FPGATrackSimOutputHeaderTool.cxx:172
FPGATrackSimLogicalEventOutputHeader
Definition: FPGATrackSimLogicalEventOutputHeader.h:12
FPGATrackSimOutputHeaderTool::m_eventOutputHeaders
std::vector< FPGATrackSimLogicalEventOutputHeader * > m_eventOutputHeaders
Definition: FPGATrackSimOutputHeaderTool.h:79
AthAlgTool
Definition: AthAlgTool.h:26
makeTOC.header
header
Definition: makeTOC.py:28
FPGATrackSimLogicalEventInputHeader.h
FPGATrackSimOutputHeaderTool::initialize
virtual StatusCode initialize() override
Definition: FPGATrackSimOutputHeaderTool.cxx:88