ATLAS Offline Software
Loading...
Searching...
No Matches
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
9FPGATrackSimOutputHeaderTool::FPGATrackSimOutputHeaderTool(std::string const & algname, std::string const & name, IInterface const * ifc) :
10 AthAlgTool(algname,name,ifc) {}
11
12
13// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
14StatusCode FPGATrackSimOutputHeaderTool::openFile(std::string const & path)
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 // Dump the configuration to make sure it propagated through right
91 const std::vector<Gaudi::Details::PropertyBase*> props = this->getProperties();
92 for( Gaudi::Details::PropertyBase* prop : props ) {
93 if (prop->ownerTypeName()==this->type()) {
94 ATH_MSG_DEBUG("Property:\t" << prop->name() << "\t : \t" << prop->toString());
95 }
96 }
97
98 ATH_CHECK(m_tHistSvc.retrieve());
99
100 if( m_rwoption.value()!=std::string("HEADER"))
101 {
102 if (m_inpath.value().empty())
103 {
104 ATH_MSG_ERROR("Empty input file list");
105 return StatusCode::FAILURE;
106 }
107 ATH_CHECK(openFile(m_inpath.value().front()));
108 }
109
110 if (m_rwoption.value() == std::string("READ")) {
111 ATH_MSG_DEBUG ("Initialized in READ MODE");
112 } else if (m_rwoption.value()==std::string("RECREATE") || m_rwoption.value()==std::string("HEADER")) {
113
114 // branches are NO LONGER created here, the user needs to do this.
115 m_EventTree = new TTree(m_treeName.value().c_str(), "data");
116
117 // For HEADER-- use THistSvc explicitly to set things up.
118 if (m_rwoption.value() == std::string("HEADER")) {
119 ATH_CHECK(m_tHistSvc->regTree(Form("/FPGATRACKSIMOUTPUT/%s", m_treeName.value().c_str()), m_EventTree));
120 }
121
122 } else {
123 ATH_MSG_ERROR ("RWstatus = " << m_rwoption.value() << " is not allowed!");
124 return StatusCode::FAILURE;
125 }
126
127 m_event = 0; // in file
128 m_totevent = 0; // total counter
129 return StatusCode::SUCCESS;
130}
131
132// Create a new input or output branch and return a pointer to the header object so code can write to it.
133// These functions work for both reading and writing.
137 m_branchNameIns.push_back(branchName);
138 if (write) {
139 m_EventTree->Branch(branchName.c_str(), "FPGATrackSimLogicalEventInputHeader", inputHeader);
140 }
141 return inputHeader;
142}
143
147 m_branchNameOuts.push_back(branchName);
148 if (write) {
149 m_EventTree->Branch(branchName.c_str(), "FPGATrackSimLogicalEventOutputHeader", outputHeader);
150 }
151 return outputHeader;
152}
153
154// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
156{
157 ATH_MSG_INFO ("finalize: closing files");
158
159 if (m_rwoption.value() == std::string("RECREATE")) {
160 ATH_MSG_INFO ("Contains " << m_EventTree->GetEntries() << " entries, over " << m_event << " events run");
161 // close the output files, but check that it exists (for athenaMP)
162 m_infile->Write();
163 }
164
165 if (m_rwoption.value() != std::string("HEADER")) {
166 m_infile->Close();
167 }
168
169 // deleting pointers
170 for (auto* header : m_eventInputHeaders) delete header;
171 for (auto* header : m_eventOutputHeaders) delete header;
172
173 return StatusCode::SUCCESS;
174}
175
176// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
177// This version of writeData assumes that the header objects were created using addInputBranch and addOutputBranch
178// and so don't need to be passed back to the tool.
180
181 if (m_rwoption.value() == std::string("READ")) {
182 ATH_MSG_WARNING ("Asked to write file in READ mode");
183 return StatusCode::SUCCESS;
184 }
185
186 ATH_MSG_DEBUG ("Writing data in TTree, event cnt=" << m_event << " limit=" << m_eventLimit << " activated" << m_activated);
187
188 // Interpret -1 as no limit.
189 if ((m_event < static_cast<unsigned>(m_eventLimit) || m_eventLimit < 0) &&
191 m_EventTree->Fill();
192 m_event++;
193 m_activated=0;
194
195 for (unsigned i = 0; i < m_eventInputHeaders.size(); i++) {
196 ATH_MSG_DEBUG("Wrote event " << m_event << " in input header (" << m_branchNameIns.at(i) << ") event " << m_eventInputHeaders.at(i)->event());
197 }
198 for (unsigned i = 0; i < m_eventOutputHeaders.size(); i++) {
199 ATH_MSG_DEBUG("Wrote event " << m_event << " in output header (" << m_branchNameOuts.at(i) << ")");
200 ATH_MSG_DEBUG("n.roads_1st = " << m_eventOutputHeaders.at(i)->nFPGATrackSimRoads_1st());
201 ATH_MSG_DEBUG("n.roads_2nd = " << m_eventOutputHeaders.at(i)->nFPGATrackSimRoads_2nd());
202 ATH_MSG_DEBUG("n.tracks_1st = " << m_eventOutputHeaders.at(i)->nFPGATrackSimTracks_1st());
203 ATH_MSG_DEBUG("n.tracks_2nd = " << m_eventOutputHeaders.at(i)->nFPGATrackSimTracks_2nd());
204 }
205 }
206
207 // Reset any input headers that we wrote out (with debugging prints).
208 for (unsigned i = 0; i < m_eventInputHeaders.size(); i++) {
209 m_eventInputHeaders.at(i)->reset();
210 }
211
212 // Reset any output headers that we wrote out (With debugging prints).
213 for (unsigned i = 0; i < m_eventOutputHeaders.size(); i++) {
214 m_eventOutputHeaders.at(i)->reset();
215 }
216
217 // Only return FAILURe if there were no input AND output headers (i.e. something is misconfigured).
218 if (m_eventInputHeaders.size() == 0 and m_eventOutputHeaders.size() == 0) {
219 ATH_MSG_ERROR("Tried to fill output ROOT file with no configured input or output headers.");
220 return StatusCode::FAILURE;
221 }
222
223 return StatusCode::SUCCESS;
224}
225
226// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
227// Since the branches are now created using the same set of functions the user already has a pointer to the object.
228// So in this function we just need to reset those objects, test last, and... call GetEntry I think.
230{
231 if (m_rwoption.value() != std::string("READ")) {
232 ATH_MSG_WARNING ("Asked to read file that is not in READ mode");
233 return StatusCode::SUCCESS;
234 }
235
236 for (auto* header : m_eventInputHeaders) {
237 header->reset();
238 }
239
240 for (auto* header : m_eventOutputHeaders) {
241 header->reset();
242 }
243
244 ATH_MSG_DEBUG ("Asked Event " << m_event << " in this file; current total is " << m_totevent);
245 last = false;
246 if (m_event >= m_EventTree->GetEntries()) {
247 if (++m_file < m_inpath.value().size()) {
248 ATH_CHECK(openFile(m_inpath.value().at(m_file)));
249 // If opening a new file we need to update the branch addresses.
251 }
252 else {
253 last = true;
254 return StatusCode::SUCCESS;
255 }
256 }
257
258 // Read the objects. I removed some of the debug messages here, they could be readded.
259 for (const std::string& branchName : m_branchNameIns) {
260 int statIn = m_EventTree->GetBranch(branchName.c_str())->GetEntry(m_event);
261 if (statIn <= 0) ATH_MSG_WARNING("Error in reading from branch " << branchName);
262 }
263
264 for (const std::string& branchName : m_branchNameOuts) {
265 int statOut = m_EventTree->GetBranch(branchName.c_str())->GetEntry(m_event);
266 if (statOut <= 0) ATH_MSG_WARNING("Error in reading from branch " << branchName);
267 }
268
269 m_event++;
270 m_totevent++;
271
272 return StatusCode::SUCCESS;
273}
274
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class reads/write FPGATrackSim output data from/to a ROOT file Designed to be not thread-safe.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
FPGATrackSimLogicalEventOutputHeader * addOutputBranch(const std::string &branchName, bool write=true)
std::vector< std::string > m_branchNameIns
Gaudi::Property< std::string > m_treeName
Gaudi::Property< std::string > m_rwoption
std::vector< std::string > m_branchNameOuts
std::vector< FPGATrackSimLogicalEventInputHeader * > m_eventInputHeaders
virtual StatusCode initialize() override
FPGATrackSimOutputHeaderTool(const std::string &, const std::string &, const IInterface *)
std::vector< FPGATrackSimLogicalEventOutputHeader * > m_eventOutputHeaders
Gaudi::Property< std::vector< std::string > > m_inpath
StatusCode openFile(std::string const &path)
FPGATrackSimLogicalEventInputHeader * addInputBranch(const std::string &branchName, bool write=true)