ATLAS Offline Software
Loading...
Searching...
No Matches
AANTupleStream.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7
9
11
12#include "Gaudi/Interfaces/IOptionsSvc.h"
13#include "GaudiKernel/IAlgManager.h"
14#include "GaudiKernel/ISvcLocator.h"
15#include "GaudiKernel/IAddressCreator.h"
16#include "GaudiKernel/IOpaqueAddress.h"
17#include "GaudiKernel/ITHistSvc.h"
18#include "GaudiKernel/ServiceHandle.h"
19#include "GaudiKernel/IIoComponentMgr.h"
20
22#include "SGTools/DataProxy.h"
24
25#include "CoralBase/AttributeList.h"
26#include "CoralBase/AttributeListSpecification.h"
27
28#include "EventInfo/EventInfo.h"
29#include "EventInfo/EventID.h"
31
32#include "TFile.h"
33#include "TTree.h"
34#include "TText.h"
35#include "TBranch.h"
36#include "TInterpreter.h"
37
38#include <map>
39#include <string>
40#include <algorithm>
41
42using namespace AANTupleParams;
43
44// Standard Constructor
45AANTupleStream::AANTupleStream(const std::string& name, ISvcLocator* pSvcLocator)
46 : base_class::base_class(name, pSvcLocator),
47 m_persSvc ("EventPersistencySvc", name),
48 m_attribSpec(0),
49 m_schemaDone(false),
50 m_tree(0),
52 m_tHistSvc ("THistSvc", name)
53{
54 declareProperty("OutputName", m_fileName="AANTuple.root");
55 declareProperty("ExtraRefNames", m_extraRefNames);
56 declareProperty("WriteInputDataHeader", m_writeInputDH=false);
57 declareProperty("ExistDataHeader", m_existDH=true);
58 declareProperty("StreamName", m_streamName=c_streamName);
59 declareProperty("LateSchemaWriting", m_lateSchema=false);
60 declareProperty("TreeName", m_treeName=c_treeName);
61 declareProperty("Macro", m_macro="");
62 declareProperty("FilterAlgs", m_acceptNames);
63
64 m_tokenCString[0] = '\0';
65}
66
67
68// Standard Destructor
72
73
74// initialize data writer
76{
77 ATH_MSG_DEBUG ("In initialize ");
78 // register with the I/O component manager
79 {
80 ServiceHandle<IIoComponentMgr> iomgr ("IoComponentMgr", this->name());
81 ATH_CHECK( iomgr.retrieve() );
82 ATH_CHECK( iomgr->io_register (this) );
83
84 if ( !iomgr->io_register (this,
85 IIoComponentMgr::IoMode::WRITE,
86 m_fileName).isSuccess() ) {
87 ATH_MSG_ERROR ("Could not register [" << this->name() << "]["
88 << m_fileName << "] with the I/O component manager !");
89 return StatusCode::FAILURE;
90 }
91 }
92
93 // StoreGateSvc
94 ATH_CHECK( evtStore().retrieve() );
95
96 // set up the persistency service:
97 ATH_CHECK( m_persSvc.retrieve() );
98
99 // instantiate AttrListSpec and add attributes for Run# and Event#
100 m_attribSpec = new coral::AttributeListSpecification;
101 m_attribSpec->extend( name_RunNumber, "unsigned int" );
102 m_attribSpec->extend( name_EventNumber, "unsigned int" );
103
104 // Add on specification for extra refs
105 for (const std::string& ref : m_extraRefNames.value())
106 {
107 // Append _ref to name of attribute
108 m_attribSpec->extend(ref + "_ref", "string");
109 }
110
111 if (!m_lateSchema) {
113 }
114
115 // get filters
117
118 ATH_MSG_DEBUG ("End initialize ");
119
120 return StatusCode::SUCCESS;
121}
122
123
124// initialize output collection
126{
127 // write schema
129
130 // setup TTree
131 setupTree();
132
133 // setup Token
134 m_tokenBranch = m_tree->GetBranch(c_tokenBranchName);
135 m_tokenBranch->SetAddress(m_tokenCString);
136
137 return StatusCode::SUCCESS;
138}
139
140
141// terminate data writer
143{
144 ATH_MSG_INFO ("finalize");
145
146 // exec macro
147 if (m_macro != "")
148 {
149 // save current dir
150 std::string curDir = gDirectory->GetPath();
151 // go to the root dir of output file
152 gDirectory->cd((m_fileName+":/").c_str());
153 // exec
154 // G__exec_tempfile(m_macro.c_str());
155 // MN: that should be the equivalent new call:
156 gInterpreter->ExecuteMacro(m_macro.c_str());
157 // back to the current dir
158 gDirectory->cd(curDir.c_str());
159 }
160
161 return StatusCode::SUCCESS;
162}
163
164
165// Work entry point
167{
168 StatusCode sc;
169
170 if (!m_schemaDone) {
171 sc = initSchema();
172 if (sc.isFailure())
173 return sc;
174 }
175
176 std::map<std::string,std::string> inputRefs;
177 std::string ref;
178
179 // Get tokens specified by item list
180 if (m_existDH)
181 {
182 // get token
185 StatusCode status = evtStore()->retrieve(beg,ending);
186 if (status.isFailure() || beg==ending)
187 {
188 ATH_MSG_WARNING ("No DataHeaders present in StoreGate");
189 return StatusCode::FAILURE;
190 }
191
192 // look for header
193 for (; beg != ending; ++beg)
194 if (m_writeInputDH == beg->isInput()) break;
195
196 if (beg==ending)
197 {
198 ATH_MSG_WARNING ("No appropriate DataHeader present in StoreGate");
199 return StatusCode::FAILURE;
200 }
201
202 // get the ref
203 while (getRef(ClassID_traits<DataHeader>::ID(), beg.key(), ref) == StatusCode::FAILURE)
204 {
205 ++beg;
206 if (beg==ending)
207 {
208 ATH_MSG_ERROR ("No refs found");
209 return StatusCode::FAILURE;
210 }
211 }
212
213 ATH_MSG_DEBUG ("Found token: Key=" << beg.key() << ", Ref=" << ref);
214
215 // Get a single input header ref if requested
216 const DataHeader* hdr = &(*beg);
217 if (hdr->sizeProvenance())
218 {
219 std::vector<DataHeaderElement>::const_iterator it =
220 (const_cast<DataHeader*>(hdr)->beginProvenance());
221 std::vector<DataHeaderElement>::const_iterator itE =
222 (const_cast<DataHeader*>(hdr)->endProvenance());
223 // grab refs for those
224 for (; it!=itE; ++it)
225 {
226 std::string tmpRef = (*it).getToken() != NULL
227 ? (*it).getToken()->toString()
228 : "";
229 inputRefs.insert(std::make_pair(it->getKey(),tmpRef));
230 ATH_MSG_DEBUG ("Found ref for input header: Key=" << it->getKey()
231 << ", Ref=" << tmpRef);
232 }
233 }
234 }
235
236 // create Attrlist, add attributes and if extra ref is requested, append to the end
237
238 ATH_MSG_DEBUG ("create AttributeList");
239 // AthenaAttributeList newAttr(*m_attribSpec);
240 coral::AttributeList newAttr(*m_attribSpec);
241
242 unsigned int runNumber = 0;
243 unsigned int eventNumber = 0;
244
245 // retrieve event info
246 const EventInfo* eventInfo;
247 eventInfo = evtStore()->tryConstRetrieve<EventInfo>();
248 if ( !eventInfo )
249 {
250 // Try to get the xAOD::EventInfo
251 const xAOD::EventInfo* eventInfoX{nullptr};
252 ATH_CHECK( evtStore()->retrieve(eventInfoX) );
253 runNumber = eventInfoX->runNumber();
254 eventNumber = eventInfoX->eventNumber();
255 }
256 else
257 {
258 runNumber = eventInfo->event_ID()->run_number();
259 eventNumber = eventInfo->event_ID()->event_number();
260 }
261
262 // add global event tag data
263 newAttr[ name_RunNumber ].setValue( runNumber );
264 newAttr[ name_EventNumber ].setValue( eventNumber );
265
266 // add back nav ref's
267 ATH_MSG_DEBUG ("Append extra ref");
268 std::vector<std::string> extraRefs = m_extraRefNames.value();
269 std::map<std::string,std::string>::iterator itRef = inputRefs.begin();
270 std::map<std::string,std::string>::iterator itRefE = inputRefs.end();
271 for (; itRef != itRefE; ++itRef)
272 {
273 std::string name = itRef->first + "_ref";
274 if (extraRefs.end() != std::find(extraRefs.begin(),extraRefs.end(),itRef->first))
275 {
276 newAttr[name].setValue(std::string(itRef->second));
277 ATH_MSG_DEBUG (" Added extra ref to new attribute list - name: "
278 << name << " " << itRef->second);
279 }
280 }
281
282 // write if filters passed
283 if (isEventAccepted())
284 {
285 ATH_MSG_DEBUG ("write attributes to collection");
286
287 // write token plus attributes
288 try
289 {
290 writeTokenAttrList(ref, newAttr);
291 }
292 catch (std::exception &e)
293 {
295 ("Caught exception from collection add of Pool attributes. "
296 "Message: " << e.what());
297 return StatusCode::FAILURE;
298 }
299 }
300
301 ATH_MSG_DEBUG ("done successfully");
302
303 return StatusCode::SUCCESS;
304}
305
306
308{
309 // go to the root dir of output file
310 TDirectory::TContext save;
311 gDirectory->cd((m_fileName+":/").c_str());
312}
313
314
316{
317 static const std::map<std::string,char> typeDict = {
318 {"double", 'D'},
319 {"long double", 'D'}, // only 64 bit doubles are supported
320 {"float", 'F'},
321 {"int", 'i'},
322 {"unsigned int", 'I'},
323 {"long", 'i'}, // support for 64 bit integers introduced with ROOT 4.00/08
324 {"unsigned long", 'I'}, // support for 64 bit integers introduced with ROOT 4.00/08
325 {"short", 's'},
326 {"unsigned short", 'S'},
327 {"char", 'b'}, // AttributeLists's "get_root_type_char(...)" returned 'C' ???
328 {"unsigned char", 'B'}, // AttributeLists's "get_root_type_char(...)" returned 's' ???
329 {"bool", 'B'}, // AttributeLists's "get_root_type_char(...)" returned 'i' ???
330 {"string", 'C'},
331 {"Token", 'C'}
332 };
333
334 // go to the root dir of output file
335 TDirectory::TContext save;
336 gDirectory->cd((m_fileName+":/").c_str());
337
338 // instantiate TTree
339 m_tree = new TTree(m_treeName.c_str(), m_treeName.c_str());
340
341 // add branches for attributes
342 for(coral::AttributeListSpecification::const_iterator iter=m_attribSpec->begin(); iter!=m_attribSpec->end(); ++iter)
343 {
344 std::string type = "/?";
345 type[1] = typeDict.at(iter->typeName());
346 std::string leaflist = iter->name() + type;
347 m_tree->Branch(iter->name().c_str(),0,leaflist.c_str());
348 }
349
350 // add Token branch
351 std::string leaflist = c_tokenBranchName;
352 leaflist += "/C";
353 m_tree->Branch(c_tokenBranchName,0,leaflist.c_str());
354
355 // set TTree
357}
358
359
360// Get the string form of a ref for a given clid and key
361StatusCode AANTupleStream::getRef(CLID id, const std::string& key, std::string& ref)
362{
363 // Must access the SG proxy to get the IOpaqueAddress
364 SG::DataProxy* itemProxy = 0;
365 ATH_MSG_DEBUG ("Retrieving proxy for " << id << " " << key);
366 itemProxy = evtStore()->proxy(id, key);
367 if (!itemProxy)
368 {
369 ATH_MSG_ERROR ("Could not get proxy ");
370 return(StatusCode::FAILURE);
371 }
372 else
373 {
374 ATH_MSG_DEBUG (" found proxy for ("<< id << ",\"" << key << "\") ");
375 }
376
377 if (!itemProxy)
378 {
379 ATH_MSG_ERROR ("Empty proxy ");
380 return(StatusCode::FAILURE);
381 }
382
383 // Get IOpaqueAddress from the proxy
384 IOpaqueAddress* addr = itemProxy->address();
385 if (!addr)
386 {
387 ATH_MSG_DEBUG ("Could not get address for clid "
388 << itemProxy->clID() << " " << itemProxy->name());
389 return( StatusCode::FAILURE);
390 }
391
392 // Convert IOpaqueAddress to string via the persistency
393 // service. And then remove header to extract the token.
394 std::string saddr;
395
396 StatusCode sc = m_persSvc->convertAddress(addr, saddr);
397 if (sc.isFailure())
398 {
400 ("Could not get string from IOpaqueAddress for clid " << id
401 << " " << key
402 << " is BAD_STORAGE_TYPE: "<< (sc == IConversionSvc::Status::BAD_STORAGE_TYPE));
403 return( StatusCode::FAILURE);
404 }
405
406
407 // We assume here some knowledge of the form of the AthenaPool
408 // string address
409 std::string hdr;
410 sc = splitAddress(saddr, " /> ", hdr, ref);
411 if (sc.isFailure())
412 {
413 ATH_MSG_ERROR ("Could not get split off token. string address " << saddr);
414 return( StatusCode::FAILURE);
415 }
416
417 ATH_MSG_DEBUG ("String address " << ref);
418
419 return StatusCode::SUCCESS;
420}
421
422
423// Extract the address header and data from an IOpaqueAddress in
424// string form
425StatusCode AANTupleStream::splitAddress( const std::string& address,
426 const std::string& match,
427 std::string& address_header,
428 std::string& address_data ) const
429{
430 ATH_MSG_DEBUG ("splitAddress " << endmsg
431 << " address : " << address
432 << " match : " << match);
433
434 std::string::size_type p1;
435
436 p1 = address.find( match );
437 if (p1 != std::string::npos)
438 {
439 address_header = address.substr( 0, p1+match.size());
440
441 address_data = address.substr( p1+match.size() );
442 }
443 else
444 {
445 return StatusCode::FAILURE;
446 }
447
448 ATH_MSG_DEBUG (" address_header : " << address_header
449 << endmsg
450 << " address_data : " << address_data);
451
452 return StatusCode::SUCCESS;
453}
454
455
456// write Token and Attributes to the output collection
457bool AANTupleStream::writeTokenAttrList( const std::string& token, const coral::AttributeList& attributeList )
458{
459 // set addresses for attributes
460 coral::AttributeList::const_iterator attIter = attributeList.begin();
461 const TObjArray* branches = m_tree->GetListOfBranches();
462 std::vector<std::string> tokenStringDump;
463 // loop over all attributes
464 for (unsigned int i=0; i<attributeList.size(); ++i)
465 {
466 TBranch* branch = (TBranch*)branches->UncheckedAt(i);
467 // string attributes
468 if (attIter->specification().type() == typeid(std::string))
469 {
470 const std::string& str = attIter->data<std::string>();
471 if( str.length()+1 >= s_maxLengthOfStrings )
472 {
473 throw std::runtime_error("String is too long : RootCollection::pool2Root<std::string>");
474 }
475 branch->SetAddress( (void*)str.c_str() );
476 }
477 // Token
478 else if(attIter->specification().typeName() == "Token")
479 {
480 tokenStringDump.push_back( attIter->data<std::string>() );
481 branch->SetAddress( (void*) tokenStringDump.back().c_str() );
482 }
483 // else
484 else
485 {
486 branch->SetAddress( (void*)attIter->addressOfData() );
487 }
488 ++attIter;
489 }
490
491 // set address for Token
492 m_tokenBranch->SetAddress((void*)token.c_str());
493
494 // fill TTree
495 m_tree->Fill();
496
497 // releases Token
498 m_tokenBranch->SetAddress(m_tokenCString);
499
500 return true;
501}
502
503
504// get filters
506{
507 ATH_MSG_DEBUG ("in getFilters()");
508
509 // no filter
510 if (m_acceptNames.empty())
511 return StatusCode::SUCCESS;
512
513 ServiceHandle<IAlgManager> theAlgMgr("ApplicationMgr", this->name());
514 ATH_CHECK( theAlgMgr.retrieve() );
515
516 // loop over all alg names
517 for (const std::string& name : m_acceptNames)
518 {
519 SmartIF<IAlgorithm> ialg{theAlgMgr->algorithm(name)};
520 if (!ialg )
521 {
522 ATH_MSG_ERROR ("Can't get Filter Alg : " << name);
523 return StatusCode::FAILURE;
524 }
525 ATH_MSG_DEBUG (" -> getting Filter Alg success " << name);
526 // push back
527 m_acceptAlgs.push_back(ialg);
528 }
529 return StatusCode::SUCCESS;
530}
531
532
533// Loop over all Algorithms in the accept list to see
534// whether any have been executed and have their filter
535// passed flag set. Any match causes the event to be
536// provisionally accepted.
538{
539 // no filter
540 if (m_acceptAlgs.empty())
541 return true;
542
543 const EventContext& ctx = Gaudi::Hive::currentContext();
544
545 // loop over all algs
546 for (const IAlgorithm* alg : m_acceptAlgs)
547 {
548 if ( alg->execState(ctx).state() == AlgExecState::State::Done &&
549 ( ! alg->execState(ctx).filterPassed() ) )
550 return false;
551 }
552
553 return true;
554}
555
556StatusCode
558{
559 m_schemaDone = true;
560
561 ATH_CHECK( m_tHistSvc.retrieve() );
562
563 // initialize output collection
565
566 // register TTree to THistSvc
567 ATH_CHECK( m_tHistSvc->regTree("/"+m_streamName+"/"+m_treeName, m_tree) );
568
570 m_tree->Print();
571
572 return StatusCode::SUCCESS;
573}
574
575StatusCode
577{
578 ServiceHandle<IIoComponentMgr> iomgr ("IoComponentMgr", this->name());
579 ATH_CHECK( iomgr.retrieve() );
580
581 ServiceHandle<Gaudi::Interfaces::IOptionsSvc> josvc ("JobOptionsSvc", this->name());
582 ATH_CHECK( josvc.retrieve() );
583
584 // check the I/O manager knows about me
585 if ( !iomgr->io_hasitem (this) ) {
586 ATH_MSG_ERROR ("I/O component mgr does not know about ourselves !");
587 return StatusCode::FAILURE;
588 }
589
590 // check there is actually something to do...
591 if ( !iomgr->io_contains (this, m_fileName) ) {
593 ("I/O component mgr does not have any entry about ["<< m_fileName<<"]");
594 return StatusCode::SUCCESS;
595 }
596
597 if ( !iomgr->io_retrieve (this, m_fileName).isSuccess() ) {
598 ATH_MSG_ERROR ("Could not retrieve new name for [" << m_fileName << "] !");
599 return StatusCode::FAILURE;
600 }
601
602 // recreate the proper property value...
603 std::vector<std::string> outvec = {"AANT DATAFILE='" + m_fileName + "' OPT='RECREATE'"};
604 josvc->set("THistSvc.Output", Gaudi::Utils::toString(outvec));
605
606 // handle schema...
607 if (!m_schemaDone) {
608 if ( !initSchema().isSuccess() ) {
609 ATH_MSG_ERROR ("Could not initialize schema !");
610 }
611 }
612
613 return StatusCode::SUCCESS;
614}
const boost::regex ref(r_ef)
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file contains the class definition for the DataHeader and DataHeaderElement classes.
This class provides a unique identification for each event, in terms of run/event number and/or a tim...
uint32_t CLID
The Class ID type.
static Double_t sc
static void setTree(const std::string &stream, TTree *tree)
Definition AANTTreeMap.h:18
virtual StatusCode execute() override
Working entry point.
void setupTree()
setup Tree
std::string m_treeName
Name of the output tree.
BooleanProperty m_lateSchema
write schema in execute()
std::string m_macro
macro
AANTupleStream(const std::string &name, ISvcLocator *pSvcLocator)
Standard AANTupleStream Constructor.
virtual ~AANTupleStream()
Standard Destructor.
StatusCode initCollection()
Initialize the output collection.
virtual StatusCode io_reinit() override
callback method to reinitialize the internal state of the component for I/O purposes (e....
bool writeTokenAttrList(const std::string &token, const coral::AttributeList &attributeList)
write Token and AttributeList
bool m_schemaDone
first event
StatusCode getFilters()
get filter alogs
ServiceHandle< IAddressCreator > m_persSvc
Persistency service.
virtual StatusCode initialize() override
Initialize AANTupleStream.
StatusCode splitAddress(const std::string &address, const std::string &match, std::string &address_header, std::string &address_data) const
Split the address to get pool token.
std::vector< IAlgorithm * > m_acceptAlgs
Vector of Algorithms that this stream accepts.
BooleanProperty m_writeInputDH
Flag to signal whether or not to write input data header.
TBranch * m_tokenBranch
TBranch which contains Token info.
char m_tokenCString[s_maxLengthOfStrings]
StringArrayProperty m_extraRefNames
Vector of extra parent ref names to register in collection.
static const unsigned int s_maxLengthOfStrings
for string branches
std::vector< std::string > m_acceptNames
Vector of names of Algorithms that this stream accepts.
coral::AttributeListSpecification * m_attribSpec
Collection attribute specification.
BooleanProperty m_existDH
Flag to signal whether data header exists.
std::string m_fileName
Name of the output collection.
virtual StatusCode finalize() override
Terminate AANTupleStream.
StatusCode getRef(CLID id, const std::string &key, std::string &ref)
Get ref from a proxy.
ServiceHandle< ITHistSvc > m_tHistSvc
THistSvc.
std::string m_streamName
Name of Stream.
StatusCode initSchema()
TTree * m_tree
TTree.
bool isEventAccepted() const
check filters passed
void writeAttributeListSpecification()
write schema of AttributeList
This class provides the layout for summary information stored for data written to POOL.
Definition DataHeader.h:123
int sizeProvenance() const
std::vector< DataHeaderElement >::const_iterator beginProvenance() const
std::vector< DataHeaderElement >::const_iterator endProvenance() const
EventID * event_ID()
the unique identification of the event.
a const_iterator facade to DataHandle.
Definition SGIterator.h:164
CLID clID() const
Retrieve clid.
virtual const name_type & name() const override final
Retrieve data object key == string.
virtual IOpaqueAddress * address() const override final
Retrieve IOpaqueAddress.
uint32_t runNumber() const
The current event's run number.
uint64_t eventNumber() const
The current event's event number.
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:359
static const std::string c_streamName
static const std::string c_treeName
EventInfo_v1 EventInfo
Definition of the latest event info version.