ATLAS Offline Software
Loading...
Searching...
No Matches
TreeBranchHelpers.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//
6// includes
7//
8
10
11// EDM include(s):
19
20// ROOT include(s):
21#include <TClass.h>
22#include <TTree.h>
23#include <TBranch.h>
24#include <TVirtualCollectionProxy.h>
25#include "Math/Vector4D.h"
26
27using ROOT::Math::PtEtaPhiEVector;
28using ROOT::Math::PtEtaPhiMVector;
29using ROOT::Math::PxPyPzEVector;
30using ROOT::Math::PxPyPzMVector;
31
32
33// System include(s):
34#include <regex>
35#include <algorithm>
36#include <functional>
37#include <sstream>
38
39//
40// method implementations
41//
42
43namespace {
44
45
46class TempInterface
47 : public SG::AuxVectorData
48{
49public:
50 TempInterface (size_t size) : m_size (size) {}
51 TempInterface (size_t size, SG::auxid_t auxid, void* ptr) :
52 m_size (size)
53 {
54 setCache (auxid, ptr);
55 }
56
57 using AuxVectorData::setStore;
58
59 size_t size_v() const override { return m_size; }
60 size_t capacity_v() const override { return m_size; }
61
62private:
63 size_t m_size;
64};
65
66
67} // anonymous namespace
68
69
70namespace {
71
72#ifdef XAOD_STANDALONE
73
86 const SG::AuxVectorBase* getVector( const std::string& key,
87 asg::SgEvent& evtStore,
88 bool allowMissing,
89 const TClass*& cl,
90 MsgStream& msg ) {
91 if( allowMissing &&
92 ( ! evtStore.contains< const SG::AuxVectorBase >( key ) ) ) {
93 return nullptr;
94 }
95 const SG::AuxVectorBase* c = nullptr;
96 if( ! evtStore.retrieve( c, key ).isSuccess() ) {
97 msg << MSG::ERROR << "Couldn't retrieve container with key \"" << key
98 << "\"" << endmsg;
99 return nullptr;
100 }
101 const xAOD::THolder* holder = evtStore.tds()->holder( key );
102 if( holder != nullptr ) {
103 // If the object is in the transient store, get the type of it from
104 // the transient store itself. So that ConstDataVector types would be
105 // handled correctly.
106 const std::type_info* ti = holder->getTypeInfo();
107 cl = TClass::GetClass( *ti );
108 } else {
109 // If the object is not in the transient store, let's just use its
110 // "actual type".
111 cl = TClass::GetClass( typeid( *c ) );
112 }
113 if( ( allowMissing == false ) && ( cl == nullptr ) ) {
114 msg << MSG::ERROR
115 << "Couldn't find TClass dictionary for container \"" << key
116 << "\"" << endmsg;
117 return nullptr;
118 }
119
120 // Return the vector object.
121 return c;
122 }
123
135 const SG::AuxElement* getElement( const std::string& key,
136 asg::SgEvent& evtStore,
137 bool allowMissing,
138 MsgStream& msg ) {
139 if( allowMissing &&
140 ( ! evtStore.contains< const SG::AuxElement >( key ) ) ) {
141 return nullptr;
142 }
143 const SG::AuxElement* e = nullptr;
144 if( ! evtStore.retrieve( e, key ).isSuccess() ) {
145 msg << MSG::ERROR << "Couldn't retrieve object with key \"" << key
146 << "\"" << endmsg;
147 return nullptr;
148 }
149 return e;
150 }
151
152#else
153
155 class ProxyWithName {
156 public:
158 typedef const SG::DataProxy* argument_type;
160 ProxyWithName( const std::string& name ) : m_name( name ) {}
162 bool operator()( argument_type proxy ) const {
163 return ( proxy->name() == m_name );
164 }
165 private:
166 std::string m_name;
167 }; // class ProxyWithName
168
181 const SG::AuxVectorBase* getVector ATLAS_NOT_CONST_THREAD_SAFE ( const std::string& key,
182 IProxyDict& evtStore,
183 bool allowMissing,
184 const TClass*& cl,
185 MsgStream& msg ) {
186
187 // Find all proxies with this key:
188 auto proxies = evtStore.proxies();
189 proxies.erase( std::remove_if( proxies.begin(), proxies.end(),
190 std::not_fn( ProxyWithName( key ) ) ),
191 proxies.end() );
192 // Now iterate over them:
193 for( const SG::DataProxy* proxy : proxies ) {
194 // We need a non-const version of it... :-(
195 SG::DataProxy* proxy_nc = const_cast< SG::DataProxy* >( proxy );
196 // Try to get the right object out of it.
197 DataBucketBase* bucket =
198 dynamic_cast< DataBucketBase* >( proxy_nc->accessData() );
199 if( ! bucket ) {
200 // This is a big problem in the job. Return right away.
201 msg << MSG::ERROR
202 << "Couldn't access data object as a data bucket?!?" << endmsg;
203 return nullptr;
204 }
205 // Get the dictionary for the type:
206 cl = TClass::GetClass( bucket->tinfo() );
207 if( ! cl ) {
208 if( msg.level() <= MSG::VERBOSE ) {
209 msg << MSG::VERBOSE << "No dictionary found for: "
210 << bucket->tinfo().name() << endmsg;
211 }
212 continue;
213 }
214 // Check whether the object inherits from AuxVectorBase:
215 if( ! cl->InheritsFrom( "SG::AuxVectorBase" ) ) {
216 if( msg.level() <= MSG::VERBOSE ) {
217 msg << MSG::VERBOSE << "Object \"" << key << "/" << cl->GetName()
218 << "\" does not inherit from SG::AuxVectorBase" << endmsg;
219 }
220 continue;
221 }
222 // If all is well, just assume that the inheritance is direct/simple:
224 reinterpret_cast< const SG::AuxVectorBase* >( bucket->object() );
225 return result;
226 }
227
228 // Apparently we failed...
229 if( ! allowMissing ) {
230 msg << MSG::ERROR << "Couldn't retrieve object \"" << key
231 << "\" as SG::AuxVectorBase" << endmsg;
232 }
233 return nullptr;
234 }
235
247 const SG::AuxElement* getElement ATLAS_NOT_CONST_THREAD_SAFE ( const std::string& key,
248 StoreGateSvc& evtStore,
249 bool allowMissing,
250 MsgStream& msg ) {
251
252
253 const SG::AuxElement* e = nullptr;
254 if( !evtStore.retrieve( e, key ).isSuccess() ) {
255 if(!allowMissing) {
256 msg << MSG::ERROR << "Couldn't retrieve object with key \"" << key
257 << "\"" << endmsg;
258 }
259 return nullptr;
260 }
261 return e;
262
263 }
264#endif // XAOD_STANDALONE
265
274 char rootType( char typeidType, MsgStream& msg ) {
275
276 // Do the hard-coded translation:
277 switch( typeidType ) {
278
279 case 'c':
280 return 'B';
281 break;
282 case 'h':
283 return 'b';
284 break;
285 case 's':
286 return 'S';
287 break;
288 case 't':
289 return 's';
290 break;
291 case 'i':
292 return 'I';
293 break;
294 case 'j':
295 return 'i';
296 break;
297 case 'f':
298 return 'F';
299 break;
300 case 'd':
301 return 'D';
302 break;
303 case 'x':
304 return 'L';
305 break;
306 case 'y':
307 case 'm': // Not sure how platform-independent this one is...
308 return 'l';
309 break;
310 case 'b':
311 return 'O';
312 break;
313 default:
314 // If we didn't find this type:
315 msg << MSG::ERROR << "Received an unknown type: " << typeidType
316 << endmsg;
317 return '\0';
318 break;
319 }
320 }
321} // private namespace
322
323namespace CP
324{
325 namespace TreeBranchHelpers
326 {
327 StatusCode BranchConfig ::
328 parse (const std::string& branchDecl, MsgStream& msg)
329 {
330 // The regular expression used to extract the needed info. The logic
331 // is supposed to be:
332 //
333 // (match[1]).(match[2])<any whitespace>-><any whitespace>(match[3])[<any whitespace>type=(match[5])][<any whitespace>metTerm=(match[7])][<any whitespace>basketSize=(match[9])]
334 //
335 // Like:
336 // "Electrons.eta -> el_eta"
337 // "Electrons.eta -> el_eta type=float"
338 // "MissingET.px -> met_px metTerm=Final"
339 static const std::regex
340 re( "\\s*([\\w%]+)\\.([\\w%]+)\\s*->\\s*([\\w%]+)(\\s+type=([\\w%]+))?(\\s+metTerm=([\\w%]+))?(\\s+basketSize=([\\w%]+))?" );
341
342 // Interpret this branch declaration.
343 std::smatch match;
344 if( ! std::regex_match( branchDecl, match, re ) ) {
345 msg << MSG::ERROR << "Expression \"" << branchDecl << "\" doesn't match \"<object>.<variable> -> <branch>\"" << endmsg;
346 return StatusCode::FAILURE;
347 }
348 this->branchDecl = branchDecl;
349 sgName = match[ 1 ];
350 auxName = match[ 2 ];
351 branchName = match[ 3 ];
352 typeName = match[ 5 ];
353 metTermName = match[ 7 ];
354 if (match[9].matched) {
355 try {
356 basketSize = std::stoi(match[9]);
357 } catch (const std::exception& ) {
358 msg << MSG::ERROR << "Could not parse basket size value: " << match[9] << endmsg;
359 return StatusCode::FAILURE;
360 }
361 }
362 return StatusCode::SUCCESS;
363 }
364
365
366
367 StatusCode BranchConfig ::
368 configureTypes (std::set<std::string>& decosWithoutType, MsgStream& msg)
369 {
370 std::string nominalAuxName = auxName;
371 if (auto pos = nominalAuxName.find ("%SYS%"); pos != std::string::npos)
372 nominalAuxName.replace (pos, 5, "NOSYS");
373 if (!typeName.empty())
374 {
375 if (typeName == "char")
376 SG::ConstAccessor<char> {nominalAuxName};
377 else if (typeName == "float")
378 SG::ConstAccessor<float> {nominalAuxName};
379 else if (typeName == "double")
380 SG::ConstAccessor<double> {nominalAuxName};
381 else if (typeName == "int")
382 SG::ConstAccessor<int> {nominalAuxName};
383 else if (typeName == "unsigned" || typeName == "unsigned_int")
384 SG::ConstAccessor<unsigned> {nominalAuxName};
385 else if (typeName == "unsigned_char")
386 SG::ConstAccessor<unsigned char> {nominalAuxName};
387 else if (typeName == "unsigned_long")
388 SG::ConstAccessor<unsigned long> {nominalAuxName};
389 else if (typeName == "unsigned_long_long")
391 else if (typeName == "int8")
392 SG::ConstAccessor<std::int8_t> {nominalAuxName};
393 else if (typeName == "int16")
394 SG::ConstAccessor<std::int16_t> {nominalAuxName};
395 else if (typeName == "int32")
396 SG::ConstAccessor<std::int32_t> {nominalAuxName};
397 else if (typeName == "int64")
398 SG::ConstAccessor<std::int64_t> {nominalAuxName};
399 else if (typeName == "uint8")
400 SG::ConstAccessor<std::uint8_t> {nominalAuxName};
401 else if (typeName == "uint16")
402 SG::ConstAccessor<std::uint16_t> {nominalAuxName};
403 else if (typeName == "uint32")
404 SG::ConstAccessor<std::uint32_t> {nominalAuxName};
405 else if (typeName == "uint64")
406 SG::ConstAccessor<std::uint64_t> {nominalAuxName};
407 else if (typeName == "vector_float")
408 SG::ConstAccessor<std::vector<float>> {nominalAuxName};
409 else if (typeName == "vector_uint8")
411 else if (typeName == "vector_int")
412 SG::ConstAccessor<std::vector<int>> {nominalAuxName};
413 else if (typeName == "vector_string")
415 else if (typeName == "vector_vector_float")
417 else if (typeName == "vector_vector_int")
419 else if (typeName == "PtEtaPhiEVector")
420 SG::ConstAccessor<PtEtaPhiEVector> {nominalAuxName};
421 else if (typeName == "PtEtaPhiMVector")
422 SG::ConstAccessor<PtEtaPhiMVector> {nominalAuxName};
423 else if (typeName == "PxPyPzEVector")
424 SG::ConstAccessor<PxPyPzEVector> {nominalAuxName};
425 else if (typeName == "PxPyPzMVector")
426 SG::ConstAccessor<PxPyPzMVector> {nominalAuxName};
427 else if (typeName == "vector_PtEtaPhiEVector")
429 else if (typeName == "vector_PtEtaPhiMVector")
431 else if (typeName == "vector_PxPyPzEVector")
433 else if (typeName == "vector_PxPyPzMVector")
435 else if (typeName == "vector_vector_PtEtaPhiEVector")
437 else if (typeName == "vector_vector_PtEtaPhiMVector")
439 else if (typeName == "vector_vector_PxPyPzEVector")
441 else if (typeName == "vector_vector_PxPyPzMVector")
443 else
444 {
445 unsigned line = __LINE__ - 2;
446 std::string file = __FILE__;
447 file = file.substr (file.find_last_of("/\\") + 1);
448 msg << MSG::ERROR << "Unknown type requested, please extend " << file << " near line " << line << " for type " << typeName << endmsg;
449 return StatusCode::FAILURE;
450 }
451 }
454 {
455 nominalAuxId = reg.findAuxID (nominalAuxName);
457 {
458 decosWithoutType.insert (nominalAuxName);
459 msg << MSG::DEBUG << "No aux ID found for auxiliary variable: " << nominalAuxName << endmsg;
460 // just returning SUCCESS here, our caller will report failure
461 return StatusCode::SUCCESS;
462 }
463 }
464 if (auxType == nullptr)
465 {
466 auxType = reg.getType (nominalAuxId);
467 if (auxType == nullptr)
468 {
469 msg << MSG::ERROR
470 << "No std::type_info available for aux-store variable: "
471 << nominalAuxName << endmsg;
472 return StatusCode::FAILURE;
473 }
474 }
475 if (auxVecType == nullptr)
476 {
477 auxVecType = reg.getVecType (nominalAuxId);
478 if (auxVecType == nullptr)
479 {
480 msg << MSG::ERROR
481 << "No std::type_info available for aux-store variable: "
482 << nominalAuxName << endmsg;
483 return StatusCode::FAILURE;
484 }
485 }
486 if (auxFactory == nullptr)
487 {
488 auxFactory = reg.getFactory (nominalAuxId);
489 if (auxFactory == nullptr)
490 {
491 msg << MSG::ERROR
492 << "No factory found for auxiliary variable: "
493 << nominalAuxName << endmsg;
494 return StatusCode::FAILURE;
495 }
496 }
497 return StatusCode::SUCCESS;
498 }
499
500
501
502 StatusCode BranchConfig ::
503 configureSystematics (ISystematicsSvc& sysSvc, MsgStream& msg)
504 {
505 if (sgName.find ("%SYS%") == std::string::npos &&
506 auxName.find ("%SYS%") == std::string::npos &&
507 branchName.find ("%SYS%") == std::string::npos)
508 {
509 nominalOnly = true;
510 }
511 if (!nominalOnly)
512 {
513 if (branchName.find ("%SYS%") == std::string::npos)
514 {
515 msg << MSG::ERROR << "Branch with systematics without %SYS% in branch name: "
516 << branchName << endmsg;
517 return StatusCode::FAILURE;
518 }
519 if (sgName.find ("%SYS%") == std::string::npos &&
520 auxName.find ("%SYS%") == std::string::npos)
521 {
522 msg << MSG::ERROR << "Branch with systematics without %SYS% in SG or aux name: "
523 << sgName << "." << auxName << endmsg;
524 return StatusCode::FAILURE;
525 }
526 if (auxName.find ("NOSYS") != std::string::npos)
527 {
528 msg << MSG::ERROR << "Branch with systematics with NOSYS in aux name: "
529 << sgName << "." << auxName << endmsg;
530 return StatusCode::FAILURE;
531 }
532 if (sgName.find ("NOSYS") != std::string::npos && auxName.find ("%SYS%") == std::string::npos)
533 {
534 msg << MSG::ERROR << "Branch with NOSYS in SG name but without %SYS% in aux name: "
535 << sgName << "." << auxName << endmsg;
536 return StatusCode::FAILURE;
537 }
538
539 if (sgName.find ("%SYS%") != std::string::npos)
541
542 if (auxName.find ("%SYS%") != std::string::npos)
543 {
544 if (auto pos = sgName.find ("NOSYS"); pos == std::string::npos)
546 else
547 {
548 // Sometimes while object systematics were applied we are not interested in them,
549 // NOSYS will then be used on the container name.
550 // Decoration systematics however will only be aware of containers with %SYS% included.
551 // Some special handling is needed to translate from NOSYS back to %SYS%.
552 std::string sgNameSys = sgName;
553 sgNameSys.replace (pos, 5, "%SYS%");
554
555 // these will be the object systematics
556 auto objectSys = sysSvc.getObjectSystematics (sgNameSys);
557
558 // these will be all systematics (object+decor)
559 auto allSys = sysSvc.getDecorSystematics (sgNameSys, auxName);
560
561 // we now need to filter-out object systematics
562 for (auto& variation : allSys)
563 {
564 if (objectSys.find (variation) == objectSys.end())
565 auxNameFilterSys.insert (variation);
566 }
567 }
568 }
569
572 if (branchNameFilterSys.empty())
573 nominalOnly = true;
574 }
575
576 return StatusCode::SUCCESS;
577 }
578
579
580
581 StatusCode OutputBranchData ::
582 configureNames (const BranchConfig& branchConfig, const CP::SystematicSet& sys, ISystematicsSvc& sysSvc, MsgStream& msg)
583 {
584 isNominal = true;
585
586 if (branchConfig.sgName.find ("%SYS%") != std::string::npos)
587 {
588 CP::SystematicSet matching;
589 if (SystematicSet::filterForAffectingSystematics (sys, branchConfig.sgNameFilterSys, matching).isFailure())
590 return StatusCode::FAILURE;
591 if (sysSvc.makeSystematicsName (sgName, branchConfig.sgName, matching).isFailure())
592 return StatusCode::FAILURE;
593 if (!matching.empty())
594 isNominal = false;
595 } else
596 sgName = branchConfig.sgName;
597
598 if (branchConfig.auxName.find ("%SYS%") != std::string::npos)
599 {
600 CP::SystematicSet matching;
601 if (SystematicSet::filterForAffectingSystematics (sys, branchConfig.auxNameFilterSys, matching).isFailure())
602 return StatusCode::FAILURE;
603 if (sysSvc.makeSystematicsName (auxName, branchConfig.auxName, matching).isFailure())
604 return StatusCode::FAILURE;
605 if (!matching.empty())
606 isNominal = false;
607 } else
608 auxName = branchConfig.auxName;
609
610 if (branchConfig.branchName.find ("%SYS%") != std::string::npos)
611 {
612 CP::SystematicSet matching;
613 if (SystematicSet::filterForAffectingSystematics (sys, branchConfig.branchNameFilterSys, matching).isFailure())
614 return StatusCode::FAILURE;
615 if (sysSvc.makeSystematicsName (branchName, branchConfig.branchName, matching).isFailure())
616 return StatusCode::FAILURE;
617 if (matching.empty() && !isNominal)
618 {
619 msg << MSG::FATAL << "Branch \"" << branchName << "\" is not affected by any of the requested systematics but is not nominal." << endmsg;
620 return StatusCode::FAILURE;
621 }
622 } else
623 {
624 branchName = branchConfig.branchName;
625 if (!sys.empty())
626 {
627 msg << MSG::FATAL << "Branch \"" << branchName << "\" without systematics is evaluated in a non-nominal context." << endmsg;
628 return StatusCode::FAILURE;
629 }
630 }
631
632 return StatusCode::SUCCESS;
633 }
634
635
636
637 StatusCode
639 setup( TTree& tree, const BranchConfig& branchConfig, OutputBranchData& outputData, MsgStream& msg ) {
640
641 // Remember the branch name.
642 m_branchName = outputData.branchName;
643
644 // Create the accessor.
645 m_acc = std::make_unique<SG::TypelessConstAccessor>( *branchConfig.auxType, outputData.auxName );
646
647 // Get a pointer to the vector factory.
648 m_factory = branchConfig.auxFactory;
649
650 // Create the data object.
651 m_data = m_factory->create( m_acc->auxid(), 1, 1, false );
652
653 // Pointer to the branch, to be created.
654 TBranch* br = nullptr;
655
656 // Decide whether we're dealing with a "primitive" or an "object" branch.
657 if( strlen( branchConfig.auxType->name() ) == 1 ) {
658
659 // This is a "primitive" variable...
660
661 // Get the type identifier for it that ROOT will understand.
662 const char rType = rootType( branchConfig.auxType->name()[ 0 ], msg );
663 if( rType == '\0' ) {
664 msg << MSG::ERROR << "Type not recognised for variable: "
665 << outputData.branchName << endmsg;
666 return StatusCode::FAILURE;
667 }
668
669 // Construct the type description.
670 std::ostringstream typeDesc;
671 typeDesc << outputData.branchName << "/" << rType;
672
673 // Create the primitive branch.
674 br = tree.Branch( outputData.branchName.c_str(), m_data->toPtr(),
675 typeDesc.str().c_str() );
676 // Check that the branch creation succeeded.
677 if( ! br ) {
678 msg << MSG::ERROR << "Failed to create branch: " << outputData.branchName
679 << endmsg;
680 return StatusCode::FAILURE;
681 }
682
683 if (branchConfig.basketSize.has_value())
684 br->SetBasketSize(branchConfig.basketSize.value());
685
686 } else {
687
688 // This is an "object" variable...
689
690 // Get a proper type name for the variable.
691 const std::string typeName = SG::normalizedTypeinfoName( *branchConfig.auxType );
692
693 // Access the dictionary for the type.
694 TClass* cl = TClass::GetClass( *branchConfig.auxType );
695 if( ! cl ) {
696 cl = TClass::GetClass( typeName.c_str() );
697 }
698 if( ! cl ) {
699 msg << MSG::ERROR << "Couldn't find dictionary for type: "
700 << typeName << endmsg;
701 return StatusCode::FAILURE;
702 }
703 if( ! cl->GetStreamerInfo() ) {
704 msg << MSG::ERROR << "No streamer info available for type: "
705 << cl->GetName() << endmsg;
706 return StatusCode::FAILURE;
707 }
708
709 // Create the object branch.
710 m_dataPtr = m_data->toPtr();
711 br = tree.Branch( outputData.branchName.c_str(), cl->GetName(), &m_dataPtr );
712 // Check that the branch creation succeeded.
713 if( ! br ) {
714 msg << MSG::ERROR << "Failed to create branch: " << outputData.branchName
715 << endmsg;
716 return StatusCode::FAILURE;
717 }
718
719 if (branchConfig.basketSize.has_value())
720 br->SetBasketSize(branchConfig.basketSize.value());
721
722 }
723
724 // Return gracefully.
725 return StatusCode::SUCCESS;
726 }
727
728 StatusCode
730 process( const SG::AuxElement& element, MsgStream& msg ) {
731
732 // A security check.
733 if( ( ! m_acc ) || ( ! m_factory ) || ( ! m_data ) ) {
734 msg << MSG::FATAL << "Internal logic error detected" << endmsg;
735 return StatusCode::FAILURE;
736 }
737
738 // Copy it into the output variable.
739 TempInterface dstiface (m_data->size(), m_acc->auxid(), m_data->toPtr());
740 m_factory->copy( m_acc->auxid(), dstiface, 0,
741 *element.container(), element.index(), 1 );
742
743 // Return gracefully.
744 return StatusCode::SUCCESS;
745 }
746
748 setup ( ROOT::RNTupleModel& /* model */, const BranchConfig& /* branchConfig */, OutputBranchData& /* outputData */, MsgStream& msg ) {
749 msg << MSG::ERROR << "ElementBranchProcessor::setup for RNTuple should not be called" << endmsg;
750 return StatusCode::FAILURE;
751 }
752
754 setup( TTree& tree, const BranchConfig& branchConfig, OutputBranchData& outputData, MsgStream& msg ) {
755
756 // Remember the branch name.
757 m_branchName = outputData.branchName;
758
759 // Create the accessor.
760 m_acc = std::make_unique<SG::TypelessConstAccessor>( *branchConfig.auxType, outputData.auxName );
761
762 // Get a pointer to the vector factory.
763 m_factory = branchConfig.auxFactory;
764
765 // Create the data object.
766 m_data = m_factory->create( m_acc->auxid(), 0, 0, false );
767
768 // Get a proper type name for the variable.
769 const std::string typeName = SG::normalizedTypeinfoName( *branchConfig.auxVecType );
770
771 // Access the dictionary for the type.
772 TClass* cl = TClass::GetClass( *branchConfig.auxVecType );
773 if( ! cl ) {
774 cl = TClass::GetClass( typeName.c_str() );
775 }
776 if( ! cl ) {
777 msg << MSG::ERROR << "Couldn't find dictionary for type: "
778 << typeName << endmsg;
779 return StatusCode::FAILURE;
780 }
781 if( ! cl->GetStreamerInfo() ) {
782 msg << MSG::ERROR << "No streamer info available for type: "
783 << cl->GetName() << endmsg;
784 return StatusCode::FAILURE;
785 }
786
787 // Create the branch.
788 m_dataPtr = m_data->toVector();
789 TBranch* br = tree.Branch( outputData.branchName.c_str(), cl->GetName(),
790 &m_dataPtr );
791 if( ! br ) {
792 msg << MSG::ERROR << "Failed to create branch: " << outputData.branchName
793 << endmsg;
794 return StatusCode::FAILURE;
795 }
796 if (branchConfig.basketSize.has_value())
797 br->SetBasketSize(branchConfig.basketSize.value());
798
799 // Return gracefully.
800 return StatusCode::SUCCESS;
801 }
802
804 resize( size_t size, MsgStream& msg ) {
805
806 // A security check.
807 if( ! m_data ) {
808 msg << MSG::FATAL << "Internal logic error detected" << endmsg;
809 return StatusCode::FAILURE;
810 }
811
812 // Do the deed.
813 m_data->resize( 0 );
814 m_data->resize( size );
815
816 // Return gracefully.
817 return StatusCode::SUCCESS;
818 }
819
821 process( const SG::AuxElement& element, size_t index, MsgStream& msg ) {
822
823 // A security check.
824 if( ( ! m_acc ) || ( ! m_factory ) || ( ! m_data ) ) {
825 msg << MSG::FATAL << "Internal logic error detected" << endmsg;
826 return StatusCode::FAILURE;
827 }
828
829 // Copy it into the output variable.
830 TempInterface dstiface (m_data->size(), m_acc->auxid(), m_data->toPtr());
831 m_factory->copy( m_acc->auxid(), dstiface, index,
832 *element.container(), element.index(), 1 );
833
834 // Return gracefully.
835 return StatusCode::SUCCESS;
836 }
837
839 setup ( ROOT::RNTupleModel& /* model */, const BranchConfig& /* branchConfig */, OutputBranchData& /* outputData */, MsgStream& msg ) {
840 msg << MSG::ERROR << "ContainerBranchProcessor::setup for RNTuple should not be called" << endmsg;
841 return StatusCode::FAILURE;
842 }
843
844
845
847 : asg::AsgMessaging( ("CP::TreeBranchHelpers::ElementProcessorRegular/" + sgName).c_str() ),
848 m_sgName(sgName) {
849
850 }
851
853 retrieveProcess( StoreType& evtStore ) {
854
855 // Retrieve the object:
856 static const bool ALLOW_MISSING = false;
857 const SG::AuxElement* el = getElement( m_sgName,
858 evtStore,
859 ALLOW_MISSING, msg() );
860 if( ! el ) {
861 ATH_MSG_ERROR( "Failed to retrieve object \"" << m_sgName
862 << "\"" );
863 return StatusCode::FAILURE;
864 }
865 const SG::AuxElement& element = *el;
866
867 // Process all branches.
868 for( auto& p : m_branches ) {
869 ATH_CHECK( p->process( element, msg() ) );
870 }
871
872 // Return gracefully.
873 return StatusCode::SUCCESS;
874 }
875
877 addBranch( TTree& tree, const BranchConfig& branchConfig, OutputBranchData& outputData ) {
878
879 // Set up the new branch.
880 m_branches.emplace_back(std::make_unique<ElementBranchProcessor>());
881 ATH_CHECK( m_branches.back()->setup( tree, branchConfig, outputData, msg() ) );
882
883 // Return gracefully.
884 return StatusCode::SUCCESS;
885 }
886
888 addBranch( ROOT::RNTupleModel& /* model */, const BranchConfig& /* branchConfig */, OutputBranchData& /* outputData */ ) {
889 ATH_MSG_ERROR("ElementProcessorRegular::addBranch for RNTuple should not be called");
890 return StatusCode::FAILURE;
891 }
892
894 : asg::AsgMessaging( ("CP::TreeBranchHelpers::ContainerProcessorRegular/" + sgName).c_str() ),
895 m_sgName(sgName) {
896
897 }
898
900 retrieveProcess( StoreType& evtStore ) {
901
902 // Retrieve the container:
903 static const bool ALLOW_MISSING = false;
904 const TClass* cl = nullptr;
905 const SG::AuxVectorBase* vec = getVector( m_sgName,
906 evtStore,
907 ALLOW_MISSING, cl, msg() );
908 if( ! vec ) {
909 ATH_MSG_ERROR( "Failed to retrieve container \""
910 << m_sgName << "\"" );
911 return StatusCode::FAILURE;
912 }
913 const SG::AuxVectorBase& container = *vec;
914
915 // Get the collection proxy for the type if it's not available yet.
916 if( ! m_collProxy ) {
917
918 // Get the collection proxy from the dictionary.
919 m_collProxy = cl->GetCollectionProxy();
920 if( ! m_collProxy ) {
921 ATH_MSG_ERROR( "No collection proxy provided by type: "
922 << cl->GetName() );
923 return StatusCode::FAILURE;
924 }
925
926 // Get the offset that one needs to use to get from the element
927 // pointers to SG::AuxElement pointers.
928 static const TClass* const auxElementClass =
929 TClass::GetClass( typeid( SG::AuxElement ) );
931 m_collProxy->GetValueClass()->GetBaseClassOffset( auxElementClass );
932 if( m_auxElementOffset < 0 ) {
933 ATH_MSG_ERROR( "Vector element type \""
934 << m_collProxy->GetValueClass()->GetName()
935 << "\" doesn't seem to inherit from \""
936 << auxElementClass->GetName() << "\"" );
937 return StatusCode::FAILURE;
938 }
939 }
940
941 // Set up the iteration over the elements of the container. In a really
942 // low level / ugly way...
943 void* cPtr =
944 const_cast< void* >( static_cast< const void* >( &container ) );
945 TVirtualCollectionProxy::TPushPop helper( m_collProxy, cPtr );
946 const UInt_t cSize = m_collProxy->Size();
947
948 // Tell all branch processors to resize their variables.
949 for( auto& p : m_branches ) {
950 ATH_CHECK( p->resize( cSize, msg() ) );
951 }
952
953 // Now iterate over the container.
954 for( UInt_t i = 0; i < cSize; ++i ) {
955
956 // Get the element.
957 char* elPtr = static_cast< char* >( m_collProxy->At( i ) );
958 if( ! elPtr ) {
959 ATH_MSG_ERROR( "Failed to get element " << i << " from container" );
960 return StatusCode::FAILURE;
961 }
962 const SG::AuxElement* element =
963 reinterpret_cast< const SG::AuxElement* >( elPtr +
965
966 // Execute all branch processors on this element.
967 for( auto& p : m_branches ) {
968 ATH_CHECK( p->process( *element, i, msg() ) );
969 }
970 }
971
972 // Return gracefully.
973 return StatusCode::SUCCESS;
974 }
975
977 addBranch( TTree& tree, const BranchConfig& branchConfig, OutputBranchData& outputData ) {
978
979 // Set up the new branch.
980 m_branches.emplace_back(std::make_unique<ContainerBranchProcessor>());
981 ATH_CHECK( m_branches.back()->setup( tree, branchConfig, outputData, msg() ) );
982
983 // Return gracefully.
984 return StatusCode::SUCCESS;
985 }
986
988 addBranch( ROOT::RNTupleModel& /* model */, const BranchConfig& /* branchConfig */, OutputBranchData& /* outputData */ ) {
989 ATH_MSG_ERROR("ContainerProcessorRegular::addBranch for RNTuple should not be called");
990 return StatusCode::FAILURE;
991 }
992
993 ElementProcessorMet::ElementProcessorMet (const std::string& sgName, const std::string& termName)
994 : asg::AsgMessaging( ("CP::TreeBranchHelpers::ElementProcessorMet/" + sgName).c_str() ),
995 m_sgName(sgName),
996 m_termName(termName) {
997
998 }
999
1001 retrieveProcess( StoreType& evtStore ) {
1002
1003 const xAOD::MissingETContainer *met = nullptr;
1004 ANA_CHECK (evtStore.retrieve (met, m_sgName));
1005 const xAOD::MissingET *term = (*met)[m_termName];
1006 if( term == nullptr ) {
1007 ANA_MSG_ERROR( "MET term " << m_termName << " not found in container " << m_sgName);
1008 return StatusCode::FAILURE;
1009 }
1010 const SG::AuxElement& element = *term;
1011 // Process all branches.
1012 for( auto& p : m_branches ) {
1013 ATH_CHECK( p->process( element, msg() ) );
1014 }
1015
1016 // Return gracefully.
1017 return StatusCode::SUCCESS;
1018 }
1019
1021 addBranch( TTree& tree, const BranchConfig& branchConfig, OutputBranchData& outputData ) {
1022
1023 // Set up the new branch.
1024 m_branches.emplace_back(std::make_unique<ElementBranchProcessor>());
1025 ATH_CHECK( m_branches.back()->setup( tree, branchConfig, outputData, msg() ) );
1026
1027 // Return gracefully.
1028 return StatusCode::SUCCESS;
1029 }
1030
1032 addBranch( ROOT::RNTupleModel& /* model */, const BranchConfig& /* branchConfig */, OutputBranchData& /* outputData */ ) {
1033 ATH_MSG_ERROR("ElementProcessorMet::addBranch for RNTuple should not be called");
1034 return StatusCode::FAILURE;
1035 }
1036
1037
1038
1039 StatusCode ProcessorList ::
1040 setupTree(const std::vector<std::string>& branches, std::unordered_set<std::string> nonContainers, ISystematicsSvc& sysSvc, TTree& tree) {
1041
1042 m_nonContainers = std::move (nonContainers);
1043
1044 std::vector<BranchConfig> branchConfigs;
1045 branchConfigs.reserve( branches.size() );
1046 for ( const std::string& branchDecl : branches ) {
1047 branchConfigs.emplace_back();
1048 ATH_CHECK( branchConfigs.back().parse( branchDecl, msg() ) );
1049 if (!branchConfigs.back().basketSize.has_value())
1050 branchConfigs.back().basketSize = defaultBasketSize;
1051 }
1052
1053 // This will loop over all branches, collect the name of any
1054 // aux-store decorations that have no type and report them at the
1055 // end. This allows to get the full list of missing decorations in
1056 // a single run, as opposed to having to re-run the job once per
1057 // missing decoration.
1058 std::set<std::string> decosWithoutType;
1059 for (auto& branchConfig : branchConfigs) {
1060 ATH_CHECK ( branchConfig.configureTypes (decosWithoutType, msg()) );
1061 }
1062 if (!decosWithoutType.empty()) {
1063 msg() << MSG::ERROR << "The following decorations have no type information:";
1064 for (const auto& deco : decosWithoutType) {
1065 msg() << " " << deco;
1066 }
1067 msg() << endmsg;
1068 return StatusCode::FAILURE;
1069 }
1070
1071
1072 for (auto& branchConfig : branchConfigs) {
1073 ATH_CHECK ( branchConfig.configureSystematics (sysSvc, msg()) );
1074 }
1075
1076 auto sysVector = sysSvc.makeSystematicsVector();
1077 // Ensure that the nominal systematic is first
1078 if (!sysVector.at(0).empty()) {
1079 ATH_MSG_ERROR ("The first systematic in the list is not nominal!");
1080 return StatusCode::FAILURE;
1081 }
1082
1083 // The branches we intend to write out
1084 std::vector<OutputBranchData> outputBranches;
1085
1086 // All the branches that will be created
1087 std::unordered_set<std::string> allBranches;
1088
1089 // Iterate over the branch specifications.
1090 for( const auto& branchConfig : branchConfigs ) {
1091
1092 // All the branches that will be created for this rule
1093 std::unordered_set<std::string> branchesForRule;
1094
1095 // Consider all systematics but skip the nominal one
1096 for( const auto& sys : sysVector ) {
1097
1098 if (branchConfig.nominalOnly && !sys.empty()) continue;
1099 OutputBranchData outputData;
1100 outputData.branchConfig = &branchConfig;
1101 outputData.sysIndex = &sys - &sysVector.front();
1102 ATH_CHECK( outputData.configureNames (branchConfig, sys, sysSvc, msg()) );
1103
1104 // Skip branches that have already been created for other
1105 // systematics for this rule. That's mostly nominal, but for
1106 // systematics correlation studies it can also do other things.
1107 if (branchesForRule.contains(outputData.branchName))
1108 {
1109 ANA_MSG_VERBOSE ("Branch \"" << outputData.branchName << "\" for rule \"" << branchConfig.branchDecl << "\" and systematic \"" << sys.name() << "\" already exists, skipping." );
1110 continue;
1111 }
1112 branchesForRule.insert(outputData.branchName);
1113
1114 // If this branch already exists from another rule, report
1115 // it as an error.
1116 if (allBranches.contains(outputData.branchName))
1117 {
1118 ANA_MSG_ERROR ("Branch \"" << outputData.branchName << "\" would be created twice!" );
1119 return StatusCode::FAILURE;
1120 }
1121 allBranches.insert(outputData.branchName);
1122 outputBranches.push_back(std::move(outputData));
1123 }
1124 }
1125
1126 // Group all branches by systematic index to ensure that when
1127 // reading a single systematic the branches are contiguous on
1128 // disk.
1129 std::stable_sort (outputBranches.begin(), outputBranches.end(),
1130 [](const OutputBranchData& a, const OutputBranchData& b) {
1131 return a.sysIndex < b.sysIndex; });
1132
1133 for (auto &outputData : outputBranches)
1134 ATH_CHECK( setupBranch( *outputData.branchConfig, outputData, tree ) );
1135
1136 // Return gracefully.
1137 return StatusCode::SUCCESS;
1138 }
1139
1140 StatusCode ProcessorList::setupBranch( const BranchConfig& branchConfig, OutputBranchData& outputData, TTree& tree ) {
1141
1142 ATH_CHECK( getObjectProcessor( branchConfig, outputData.sgName ).addBranch( tree,
1143 branchConfig, outputData ) );
1144 ATH_MSG_DEBUG( "Writing branch \"" << outputData.branchName
1145 << "\" from container/variable \"" << outputData.sgName
1146 << "." << outputData.auxName << "\"" );
1147
1148 // Return gracefully.
1149 return StatusCode::SUCCESS;
1150 }
1151
1152 StatusCode ProcessorList ::
1153 process (StoreType& evtStore)
1154 {
1155 // Process the standalone objects:
1156 for( auto& [name, processor] : m_processors )
1157 {
1158 // Process it:
1159 ATH_CHECK (processor->retrieveProcess (evtStore));
1160 }
1161 return StatusCode::SUCCESS;
1162 }
1163
1164
1165
1166 IObjectProcessor& ProcessorList ::
1167 getObjectProcessor( const BranchConfig& branchConfig, const std::string& sgName )
1168 {
1169 std::string processorName = sgName;
1170 if (!branchConfig.metTermName.empty())
1171 processorName += ":metTerm=" + branchConfig.metTermName;
1172
1173 if (auto iter = m_processors.find(processorName); iter != m_processors.end())
1174 return *iter->second;
1175
1176 if (!branchConfig.metTermName.empty())
1177 return *m_processors.emplace (processorName, std::make_unique<ElementProcessorMet>(sgName, branchConfig.metTermName)).first->second;
1178
1179 if (m_nonContainers.contains(sgName))
1180 return *m_processors.emplace (processorName, std::make_unique<ElementProcessorRegular>(sgName)).first->second;
1181
1182 return *m_processors.emplace (processorName, std::make_unique<ContainerProcessorRegular>(sgName)).first->second;
1183 }
1184 }
1185}
const std::regex re(r_e)
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
Base class for elements of a container that can have aux data.
Manage index tracking and synchronization of auxiliary data.
std::vector< size_t > vec
#define ANA_MSG_ERROR(xmsg,...)
Macro printing error messages.
#define ANA_MSG_VERBOSE(xmsg,...)
Macro printing verbose messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
Interface providing I/O for a generic auxiliary store.
Interface for factory objects that create vectors.
static Double_t a
static HEPVis_BooleanProcessor processor
void operator()(T1)
size_t size() const
Number of registered mappings.
#define ATLAS_NOT_CONST_THREAD_SAFE
the interface for the central systematics service
virtual CP::SystematicSet getObjectSystematics(const std::string &name) const =0
get the systematics for the given object in the event store
virtual std::vector< CP::SystematicSet > makeSystematicsVector() const =0
get the list of systematics
virtual CP::SystematicSet getDecorSystematics(const std::string &objectName, const std::string &decorName) const =0
get the systematics for the given object in the event store
virtual StatusCode makeSystematicsName(std::string &result, const std::string &name, const CP::SystematicSet &sys) const =0
make the name for the given systematics
Class to wrap a set of SystematicVariations.
bool empty() const
returns: whether the set is empty
static StatusCode filterForAffectingSystematics(const SystematicSet &systConfig, const SystematicSet &affectingSystematics, SystematicSet &filteredSystematics)
description: filter the systematics for the affected systematics returns: success guarantee: strong f...
std::string m_branchName
Name of the branch being written.
StatusCode resize(size_t size, MsgStream &msg)
Function (re)sizing the variable for a new event.
std::unique_ptr< SG::IAuxTypeVector > m_data
The object managing the memory of the written variable.
StatusCode process(const SG::AuxElement &element, size_t index, MsgStream &msg)
Function processing the object, filling the variable.
std::unique_ptr< SG::TypelessConstAccessor > m_acc
Object accessing the variable in question.
virtual StatusCode setup(TTree &tree, const BranchConfig &branchConfig, OutputBranchData &outputData, MsgStream &msg) override
Function setting up the object, and the branch.
const SG::IAuxTypeVectorFactory * m_factory
Pointer to the helper object that handles this variable.
void * m_dataPtr
Helper variable, pointing at the object to be written.
TVirtualCollectionProxy * m_collProxy
Collection proxy used for iterating over the container.
std::string m_sgName
Name of the object in the event store.
int m_auxElementOffset
Offset of the element type to SG::AuxElement.
virtual StatusCode retrieveProcess(StoreType &evtStore) override
retrieve and process the object
virtual StatusCode addBranch(TTree &tree, const BranchConfig &branchConfig, OutputBranchData &outputData) override
Add one branch to the output tree.
std::vector< std::unique_ptr< ContainerBranchProcessor > > m_branches
List of branch processors set up for this xAOD object.
ContainerProcessorRegular(const std::string &sgName)
Default constructor.
std::unique_ptr< SG::IAuxTypeVector > m_data
The object managing the memory of the written variable.
void * m_dataPtr
Helper variable, pointing at the object to be written.
const SG::IAuxTypeVectorFactory * m_factory
Pointer to the helper object that handles this variable.
std::string m_branchName
Name of the branch being written.
virtual StatusCode setup(TTree &tree, const BranchConfig &branchConfig, OutputBranchData &outputData, MsgStream &msg) override
Function setting up the object, and the branch.
std::unique_ptr< SG::TypelessConstAccessor > m_acc
Object accessing the variable in question.
StatusCode process(const SG::AuxElement &element, MsgStream &msg)
Function processing the object, filling the variable.
std::vector< std::unique_ptr< ElementBranchProcessor > > m_branches
List of branch processors set up for this xAOD object.
std::string m_termName
Name of the MET term to retrieve.
virtual StatusCode addBranch(TTree &tree, const BranchConfig &branchConfig, OutputBranchData &outputData) override
Add one branch to the output tree.
ElementProcessorMet(const std::string &sgName, const std::string &termName)
Default constructor.
virtual StatusCode retrieveProcess(StoreType &evtStore) override
retrieve and process the object
std::string m_sgName
Name of the object in the event store.
virtual StatusCode retrieveProcess(StoreType &evtStore) override
retrieve and process the object
virtual StatusCode addBranch(TTree &tree, const BranchConfig &branchConfig, OutputBranchData &outputData) override
Add one branch to the output tree.
std::string m_sgName
Name of the object in the event store.
ElementProcessorRegular(const std::string &sgName)
Default constructor.
std::vector< std::unique_ptr< ElementBranchProcessor > > m_branches
List of branch processors set up for this xAOD object.
the interface class for classes reading an object from the event store and processing it
virtual StatusCode addBranch(TTree &, const BranchConfig &, OutputBranchData &)=0
Add one branch to the output tree.
StatusCode setupBranch(const BranchConfig &branchConfig, OutputBranchData &outputData, TTree &tree)
Function setting up an individual branch on the first event.
std::unordered_set< std::string > m_nonContainers
the non-containers
IObjectProcessor & getObjectProcessor(const BranchConfig &branchConfig, const std::string &sgName)
std::optional< int > defaultBasketSize
the default basket size
std::unordered_map< std::string, std::unique_ptr< IObjectProcessor > > m_processors
object processors
A non-templated base class for DataBucket, allows to access the transient object address as a void*.
virtual void * object()=0
virtual const std::type_info & tinfo() const =0
Return the type_info for the stored object.
virtual std::vector< const SG::DataProxy * > proxies() const =0
Return the list of all current proxies in store.
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Manage index tracking and synchronization of auxiliary data.
Manage lookup of vectors of auxiliary data.
Helper class to provide constant type-safe access to aux data.
DataObject * accessData()
Access DataObject on-demand using conversion service.
The Athena Transient Store API.
StatusCode retrieve(const T *&ptr) const
Retrieve the default object into a const T*.
MsgStream & msg() const
The standard message stream.
MsgStream & msg() const
The standard message stream.
AsgMessaging(const std::string &name)
Constructor with a name.
Wrapper for Event to make it look like StoreGate.
Definition SgEvent.h:44
bool contains(const std::string &name) const
Check if an object is available for constant access.
xAOD::TStore * tds() const
Return the underlying transient data store.
Definition SgEvent.cxx:33
T * retrieve(const std::string &name) const
Function retrieving a constant or non-constant object.
This class takes care of holding EDM objects in memory.
Definition THolder.h:35
const std::type_info * getTypeInfo() const
Definition THolder.cxx:412
const THolder * holder(const std::string &key) const
return holder for key
Definition TStore.cxx:50
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:359
a namespace for helper functions and objects for filling tree branches
StoreGateSvc StoreType
the type of the event store in the current environment
Select isolated Photons, Electrons and Muons.
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
virtual const IAuxTypeVector * getVector(SG::auxid_t auxid) const override
Return vector interface for one aux data item.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition index.py:1
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
char rootType(char typeidType)
This function is used internally in the code when creating primitive dynamic auxiliary branches.
MissingET_v1 MissingET
Version control by type defintion.
Definition MissingET.h:15
MissingETContainer_v1 MissingETContainer
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
the user configuration of an output branch
std::string branchDecl
the original user configuration string
std::string sgName
the SG name of the object to read from
const SG::IAuxTypeVectorFactory * auxFactory
pointer to the aux vector factory
std::string auxName
the aux data variable name to read from
const std::type_info * auxVecType
the vector type of the decoration we read
std::optional< int > basketSize
the basket size for this branch
CP::SystematicSet auxNameFilterSys
the affecting systematics for the auxName
CP::SystematicSet sgNameFilterSys
the affecting systematics for the sgName
CP::SystematicSet branchNameFilterSys
the affecting systematics for the branchName
const std::type_info * auxType
the type of the decoration we read
SG::auxid_t nominalAuxId
the aux-id for the nominal decoration
std::string branchName
the name of the output branch
std::string metTermName
MET ONLY: the name of the MET term to write out.
bool nominalOnly
whether we only want to write out the nominal
std::string typeName
the name of the type (or empty to read from aux-registry)
the data for a single output branch
bool isNominal
whether this is unaffected by systematics (i.e. nominal)
const BranchConfig * branchConfig
the BranchConfig we are based on
std::size_t sysIndex
the index in the systematics list
StatusCode configureNames(const BranchConfig &branchConfig, const CP::SystematicSet &sys, ISystematicsSvc &sysSvc, MsgStream &msg)
configure names for systematics
std::string auxName
the name of the decoration in the aux-store
std::string sgName
the SG name of the object to read from
std::string branchName
the name of the output branch
MsgStream & msg
Definition testRead.cxx:32
TChain * tree
TFile * file