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 const std::string refStr{"_ref"};
104 const std::string stringTypeStr{"string"};
105 // Add on specification for extra refs
106 for (const std::string& ref : m_extraRefNames.value())
107 {
108 // Append _ref to name of attribute
109 m_attribSpec->extend(ref + refStr, stringTypeStr);
110 }
111
112 if (!m_lateSchema) {
114 }
115
116 // get filters
118
119 ATH_MSG_DEBUG ("End initialize ");
120
121 return StatusCode::SUCCESS;
122}
123
124
125// initialize output collection
127{
128 // write schema
130
131 // setup TTree
132 setupTree();
133
134 // setup Token
135 m_tokenBranch = m_tree->GetBranch(c_tokenBranchName);
136 m_tokenBranch->SetAddress(m_tokenCString);
137
138 return StatusCode::SUCCESS;
139}
140
141
142// terminate data writer
144{
145 ATH_MSG_INFO ("finalize");
146
147 // exec macro
148 if (m_macro != "")
149 {
150 // save current dir
151 std::string curDir = gDirectory->GetPath();
152 // go to the root dir of output file
153 gDirectory->cd((m_fileName+":/").c_str());
154 // exec
155 // G__exec_tempfile(m_macro.c_str());
156 // MN: that should be the equivalent new call:
157 gInterpreter->ExecuteMacro(m_macro.c_str());
158 // back to the current dir
159 gDirectory->cd(curDir.c_str());
160 }
161
162 return StatusCode::SUCCESS;
163}
164
165
166// Work entry point
167StatusCode AANTupleStream::execute(const EventContext& /*ctx*/)
168{
169 StatusCode sc;
170
171 if (!m_schemaDone) {
172 sc = initSchema();
173 if (sc.isFailure())
174 return sc;
175 }
176
177 std::map<std::string,std::string> inputRefs;
178 std::string ref;
179
180 // Get tokens specified by item list
181 if (m_existDH)
182 {
183 // get token
186 StatusCode status = evtStore()->retrieve(beg,ending);
187 if (status.isFailure() || beg==ending)
188 {
189 ATH_MSG_WARNING ("No DataHeaders present in StoreGate");
190 return StatusCode::FAILURE;
191 }
192
193 // look for header
194 for (; beg != ending; ++beg)
195 if (m_writeInputDH == beg->isInput()) break;
196
197 if (beg==ending)
198 {
199 ATH_MSG_WARNING ("No appropriate DataHeader present in StoreGate");
200 return StatusCode::FAILURE;
201 }
202
203 // get the ref
204 while (getRef(ClassID_traits<DataHeader>::ID(), beg.key(), ref) == StatusCode::FAILURE)
205 {
206 ++beg;
207 if (beg==ending)
208 {
209 ATH_MSG_ERROR ("No refs found");
210 return StatusCode::FAILURE;
211 }
212 }
213
214 ATH_MSG_DEBUG ("Found token: Key=" << beg.key() << ", Ref=" << ref);
215
216 // Get a single input header ref if requested
217 const DataHeader* hdr = &(*beg);
218 if (hdr->sizeProvenance())
219 {
220 std::vector<DataHeaderElement>::const_iterator it =
221 (const_cast<DataHeader*>(hdr)->beginProvenance());
222 std::vector<DataHeaderElement>::const_iterator itE =
223 (const_cast<DataHeader*>(hdr)->endProvenance());
224 // grab refs for those
225 for (; it!=itE; ++it)
226 {
227 std::string tmpRef = (*it).getToken() != NULL
228 ? (*it).getToken()->toString()
229 : "";
230 inputRefs.insert(std::make_pair(it->getKey(),tmpRef));
231 ATH_MSG_DEBUG ("Found ref for input header: Key=" << it->getKey()
232 << ", Ref=" << tmpRef);
233 }
234 }
235 }
236
237 // create Attrlist, add attributes and if extra ref is requested, append to the end
238
239 ATH_MSG_DEBUG ("create AttributeList");
240 // AthenaAttributeList newAttr(*m_attribSpec);
241 coral::AttributeList newAttr(*m_attribSpec);
242
243 unsigned int runNumber = 0;
244 unsigned int eventNumber = 0;
245
246 // retrieve event info
247 const EventInfo* eventInfo;
248 eventInfo = evtStore()->tryConstRetrieve<EventInfo>();
249 if ( !eventInfo )
250 {
251 // Try to get the xAOD::EventInfo
252 const xAOD::EventInfo* eventInfoX{nullptr};
253 ATH_CHECK( evtStore()->retrieve(eventInfoX) );
254 runNumber = eventInfoX->runNumber();
255 eventNumber = eventInfoX->eventNumber();
256 }
257 else
258 {
259 runNumber = eventInfo->event_ID()->run_number();
260 eventNumber = eventInfo->event_ID()->event_number();
261 }
262
263 // add global event tag data
264 newAttr[ name_RunNumber ].setValue( runNumber );
265 newAttr[ name_EventNumber ].setValue( eventNumber );
266
267 // add back nav ref's
268 ATH_MSG_DEBUG ("Append extra ref");
269 std::vector<std::string> extraRefs = m_extraRefNames.value();
270 std::map<std::string,std::string>::iterator itRef = inputRefs.begin();
271 std::map<std::string,std::string>::iterator itRefE = inputRefs.end();
272 for (; itRef != itRefE; ++itRef)
273 {
274 std::string name = itRef->first + "_ref";
275 if (extraRefs.end() != std::find(extraRefs.begin(),extraRefs.end(),itRef->first))
276 {
277 newAttr[name].setValue(std::string(itRef->second));
278 ATH_MSG_DEBUG (" Added extra ref to new attribute list - name: "
279 << name << " " << itRef->second);
280 }
281 }
282
283 // write if filters passed
284 if (isEventAccepted())
285 {
286 ATH_MSG_DEBUG ("write attributes to collection");
287
288 // write token plus attributes
289 try
290 {
291 writeTokenAttrList(ref, newAttr);
292 }
293 catch (std::exception &e)
294 {
296 ("Caught exception from collection add of Pool attributes. "
297 "Message: " << e.what());
298 return StatusCode::FAILURE;
299 }
300 }
301
302 ATH_MSG_DEBUG ("done successfully");
303
304 return StatusCode::SUCCESS;
305}
306
307
309{
310 // go to the root dir of output file
311 TDirectory::TContext save;
312 gDirectory->cd((m_fileName+":/").c_str());
313}
314
315
317{
318 static const std::map<std::string,char> typeDict = {
319 {"double", 'D'},
320 {"long double", 'D'}, // only 64 bit doubles are supported
321 {"float", 'F'},
322 {"int", 'i'},
323 {"unsigned int", 'I'},
324 {"long", 'i'}, // support for 64 bit integers introduced with ROOT 4.00/08
325 {"unsigned long", 'I'}, // support for 64 bit integers introduced with ROOT 4.00/08
326 {"short", 's'},
327 {"unsigned short", 'S'},
328 {"char", 'b'}, // AttributeLists's "get_root_type_char(...)" returned 'C' ???
329 {"unsigned char", 'B'}, // AttributeLists's "get_root_type_char(...)" returned 's' ???
330 {"bool", 'B'}, // AttributeLists's "get_root_type_char(...)" returned 'i' ???
331 {"string", 'C'},
332 {"Token", 'C'}
333 };
334
335 // go to the root dir of output file
336 TDirectory::TContext save;
337 gDirectory->cd((m_fileName+":/").c_str());
338
339 // instantiate TTree
340 m_tree = new TTree(m_treeName.c_str(), m_treeName.c_str());
341
342 // add branches for attributes
343 for(coral::AttributeListSpecification::const_iterator iter=m_attribSpec->begin(); iter!=m_attribSpec->end(); ++iter)
344 {
345 std::string type = "/?";
346 type[1] = typeDict.at(iter->typeName());
347 std::string leaflist = iter->name() + type;
348 m_tree->Branch(iter->name().c_str(),0,leaflist.c_str());
349 }
350
351 // add Token branch
352 std::string leaflist = c_tokenBranchName;
353 leaflist += "/C";
354 m_tree->Branch(c_tokenBranchName,0,leaflist.c_str());
355
356 // set TTree
358}
359
360
361// Get the string form of a ref for a given clid and key
362StatusCode AANTupleStream::getRef(CLID id, const std::string& key, std::string& ref)
363{
364 // Must access the SG proxy to get the IOpaqueAddress
365 SG::DataProxy* itemProxy = 0;
366 ATH_MSG_DEBUG ("Retrieving proxy for " << id << " " << key);
367 itemProxy = evtStore()->proxy(id, key);
368 if (!itemProxy)
369 {
370 ATH_MSG_ERROR ("Could not get proxy ");
371 return(StatusCode::FAILURE);
372 }
373 else
374 {
375 ATH_MSG_DEBUG (" found proxy for ("<< id << ",\"" << key << "\") ");
376 }
377
378 if (!itemProxy)
379 {
380 ATH_MSG_ERROR ("Empty proxy ");
381 return(StatusCode::FAILURE);
382 }
383
384 // Get IOpaqueAddress from the proxy
385 IOpaqueAddress* addr = itemProxy->address();
386 if (!addr)
387 {
388 ATH_MSG_DEBUG ("Could not get address for clid "
389 << itemProxy->clID() << " " << itemProxy->name());
390 return( StatusCode::FAILURE);
391 }
392
393 // Convert IOpaqueAddress to string via the persistency
394 // service. And then remove header to extract the token.
395 std::string saddr;
396
397 StatusCode sc = m_persSvc->convertAddress(addr, saddr);
398 if (sc.isFailure())
399 {
401 ("Could not get string from IOpaqueAddress for clid " << id
402 << " " << key
403 << " is BAD_STORAGE_TYPE: "<< (sc == IConversionSvc::Status::BAD_STORAGE_TYPE));
404 return( StatusCode::FAILURE);
405 }
406
407
408 // We assume here some knowledge of the form of the AthenaPool
409 // string address
410 std::string hdr;
411 sc = splitAddress(saddr, " /> ", hdr, ref);
412 if (sc.isFailure())
413 {
414 ATH_MSG_ERROR ("Could not get split off token. string address " << saddr);
415 return( StatusCode::FAILURE);
416 }
417
418 ATH_MSG_DEBUG ("String address " << ref);
419
420 return StatusCode::SUCCESS;
421}
422
423
424// Extract the address header and data from an IOpaqueAddress in
425// string form
426StatusCode AANTupleStream::splitAddress( const std::string& address,
427 const std::string& match,
428 std::string& address_header,
429 std::string& address_data ) const
430{
431 ATH_MSG_DEBUG ("splitAddress " << endmsg
432 << " address : " << address
433 << " match : " << match);
434
435 std::string::size_type p1;
436
437 p1 = address.find( match );
438 if (p1 != std::string::npos)
439 {
440 address_header = address.substr( 0, p1+match.size());
441
442 address_data = address.substr( p1+match.size() );
443 }
444 else
445 {
446 return StatusCode::FAILURE;
447 }
448
449 ATH_MSG_DEBUG (" address_header : " << address_header
450 << endmsg
451 << " address_data : " << address_data);
452
453 return StatusCode::SUCCESS;
454}
455
456
457// write Token and Attributes to the output collection
458bool AANTupleStream::writeTokenAttrList( const std::string& token, const coral::AttributeList& attributeList )
459{
460 // set addresses for attributes
461 coral::AttributeList::const_iterator attIter = attributeList.begin();
462 const TObjArray* branches = m_tree->GetListOfBranches();
463 std::vector<std::string> tokenStringDump;
464 // loop over all attributes
465 for (unsigned int i=0; i<attributeList.size(); ++i)
466 {
467 TBranch* branch = (TBranch*)branches->UncheckedAt(i);
468 // string attributes
469 if (attIter->specification().type() == typeid(std::string))
470 {
471 const std::string& str = attIter->data<std::string>();
472 if( str.length()+1 >= s_maxLengthOfStrings )
473 {
474 throw std::runtime_error("String is too long : RootCollection::pool2Root<std::string>");
475 }
476 branch->SetAddress( (void*)str.c_str() );
477 }
478 // Token
479 else if(attIter->specification().typeName() == "Token")
480 {
481 tokenStringDump.push_back( attIter->data<std::string>() );
482 branch->SetAddress( (void*) tokenStringDump.back().c_str() );
483 }
484 // else
485 else
486 {
487 branch->SetAddress( (void*)attIter->addressOfData() );
488 }
489 ++attIter;
490 }
491
492 // set address for Token
493 m_tokenBranch->SetAddress((void*)token.c_str());
494
495 // fill TTree
496 m_tree->Fill();
497
498 // releases Token
499 m_tokenBranch->SetAddress(m_tokenCString);
500
501 return true;
502}
503
504
505// get filters
507{
508 ATH_MSG_DEBUG ("in getFilters()");
509
510 // no filter
511 if (m_acceptNames.empty())
512 return StatusCode::SUCCESS;
513
514 ServiceHandle<IAlgManager> theAlgMgr("ApplicationMgr", this->name());
515 ATH_CHECK( theAlgMgr.retrieve() );
516
517 // loop over all alg names
518 for (const std::string& name : m_acceptNames)
519 {
520 SmartIF<IAlgorithm> ialg{theAlgMgr->algorithm(name)};
521 if (!ialg )
522 {
523 ATH_MSG_ERROR ("Can't get Filter Alg : " << name);
524 return StatusCode::FAILURE;
525 }
526 ATH_MSG_DEBUG (" -> getting Filter Alg success " << name);
527 // push back
528 m_acceptAlgs.push_back(ialg);
529 }
530 return StatusCode::SUCCESS;
531}
532
533
534// Loop over all Algorithms in the accept list to see
535// whether any have been executed and have their filter
536// passed flag set. Any match causes the event to be
537// provisionally accepted.
539{
540 // no filter
541 if (m_acceptAlgs.empty())
542 return true;
543
544 const EventContext& ctx = Gaudi::Hive::currentContext();
545
546 // loop over all algs
547 for (const IAlgorithm* alg : m_acceptAlgs)
548 {
549 if ( alg->execState(ctx).state() == AlgExecState::State::Done &&
550 ( ! alg->execState(ctx).filterPassed() ) )
551 return false;
552 }
553
554 return true;
555}
556
557StatusCode
559{
560 m_schemaDone = true;
561
562 ATH_CHECK( m_tHistSvc.retrieve() );
563
564 // initialize output collection
566
567 // register TTree to THistSvc
568 ATH_CHECK( m_tHistSvc->regTree("/"+m_streamName+"/"+m_treeName, m_tree) );
569
571 m_tree->Print();
572
573 return StatusCode::SUCCESS;
574}
575
576StatusCode
578{
579 ServiceHandle<IIoComponentMgr> iomgr ("IoComponentMgr", this->name());
580 ATH_CHECK( iomgr.retrieve() );
581
582 ServiceHandle<Gaudi::Interfaces::IOptionsSvc> josvc ("JobOptionsSvc", this->name());
583 ATH_CHECK( josvc.retrieve() );
584
585 // check the I/O manager knows about me
586 if ( !iomgr->io_hasitem (this) ) {
587 ATH_MSG_ERROR ("I/O component mgr does not know about ourselves !");
588 return StatusCode::FAILURE;
589 }
590
591 // check there is actually something to do...
592 if ( !iomgr->io_contains (this, m_fileName) ) {
594 ("I/O component mgr does not have any entry about ["<< m_fileName<<"]");
595 return StatusCode::SUCCESS;
596 }
597
598 if ( !iomgr->io_retrieve (this, m_fileName).isSuccess() ) {
599 ATH_MSG_ERROR ("Could not retrieve new name for [" << m_fileName << "] !");
600 return StatusCode::FAILURE;
601 }
602
603 // recreate the proper property value...
604 std::vector<std::string> outvec = {"AANT DATAFILE='" + m_fileName + "' OPT='RECREATE'"};
605 josvc->set("THistSvc.Output", Gaudi::Utils::toString(outvec));
606
607 // handle schema...
608 if (!m_schemaDone) {
609 if ( !initSchema().isSuccess() ) {
610 ATH_MSG_ERROR ("Could not initialize schema !");
611 }
612 }
613
614 return StatusCode::SUCCESS;
615}
const std::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
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.
virtual StatusCode execute(const EventContext &ctx) override
Working entry point.
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.