58 #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
59 char* operator+( streampos&,
char* );
62 ClassImp(RooAbsCollection);
68 RooAbsCollection::RooAbsCollection() :
82 RooAbsCollection::RooAbsCollection(
const char *name) :
98 RooAbsCollection::RooAbsCollection(
const RooAbsCollection& other,
const char *name) :
104 _allRRV(other._allRRV)
106 RooTrace::create(
this) ;
107 if (!name) setName(other.GetName()) ;
109 _list.reserve(other._list.size());
111 for (
auto item : other._list) {
121 RooAbsCollection::~RooAbsCollection()
135 void RooAbsCollection::safeDeleteList()
138 if (_list.size() > 1) {
139 std::vector<RooAbsArg*> tmp;
140 tmp.reserve(_list.size());
143 for (
auto arg : _list) {
145 if (!arg->dependsOn(*
this, arg)) tmp.push_back(arg);
149 std::sort(tmp.begin(), tmp.end());
151 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
153 auto newEnd = _list.end();
154 for (
auto item : tmp) {
155 newEnd = std::remove(_list.begin(), newEnd, item);
158 _list.erase(newEnd, _list.end());
159 }
while (!tmp.empty() && _list.size() > 1);
162 if (_list.size() > 1) {
163 coutW(ObjectHandling) <<
"RooAbsCollection::safeDeleteList(" << GetName()
164 <<
") WARNING: unable to delete following elements in client-server order " ;
170 for (
auto item : _list) {
194 RooAbsCollection* RooAbsCollection::snapshot(Bool_t deepCopy)
const
198 if (TString(GetName()).Length()>0) {
199 snapName.Append(
"Snapshot of ") ;
200 snapName.Append(GetName()) ;
202 RooAbsCollection* output = (RooAbsCollection*) create(snapName.Data()) ;
204 Bool_t error = snapshot(*output,deepCopy) ;
230 Bool_t RooAbsCollection::snapshot(RooAbsCollection& output, Bool_t deepCopy)
const
233 output.reserve(_list.size());
234 for (
auto orig : _list) {
235 RooAbsArg *copy= (RooAbsArg*)orig->Clone();
240 Bool_t error(kFALSE) ;
244 for (Storage_t::size_type i = 0; i < output._list.size(); ++i) {
245 const auto var = output._list[i];
246 error |= output.addServerClonesToList(*var);
252 coutE(ObjectHandling) <<
"RooAbsCollection::snapshot(): Errors occurred in deep clone process, snapshot not created" << endl ;
253 output._ownCont = kTRUE ;
260 for (
auto var : output) {
261 var->redirectServers(output,deepCopy);
266 output._ownCont = kTRUE ;
275 Bool_t RooAbsCollection::addServerClonesToList(
const RooAbsArg& var)
279 for (
const auto server : var.servers()) {
280 RooAbsArg* tmp = find(*server) ;
283 RooAbsArg* serverClone = (RooAbsArg*)server->Clone() ;
284 serverClone->setAttribute(
"SnapShot_ExtRefClone") ;
285 _list.push_back(serverClone) ;
286 if (_allRRV && dynamic_cast<RooRealVar*>(serverClone)==0) {
289 ret |= addServerClonesToList(*server) ;
304 RooAbsCollection &RooAbsCollection::operator=(
const RooAbsCollection& other)
306 if (&other==
this)
return *this ;
308 for (
auto elem : _list) {
309 auto theirs = other.find(*elem);
310 if(!theirs)
continue;
311 theirs->syncCache() ;
312 elem->copyCache(theirs) ;
313 elem->setAttribute(
"Constant",theirs->isConstant()) ;
324 RooAbsCollection &RooAbsCollection::assignValueOnly(
const RooAbsCollection& other, Bool_t oneSafe)
326 if (&other==
this)
return *this ;
329 if (getSize()==1 && getSize()==other.getSize() && oneSafe) {
330 other.first()->syncCache() ;
331 first()->copyCache(other.first(),kTRUE) ;
335 for (
auto elem : _list) {
336 auto theirs = other.find(*elem);
337 if(!theirs)
continue;
338 theirs->syncCache() ;
339 elem->copyCache(theirs,kTRUE) ;
350 void RooAbsCollection::assignFast(
const RooAbsCollection& other, Bool_t setValDirty)
352 if (&other==
this) return ;
353 assert(_list.size() == other._list.size());
355 auto iter2 = other._list.begin();
356 for (
auto iter1 = _list.begin();
357 iter1 != _list.end() && iter2 != other._list.end();
363 auto ours =
static_cast<RooRealVar*
>(*iter1);
364 auto theirs =
static_cast<RooRealVar*
>(*iter2);
365 ours->copyCacheFast(*theirs,setValDirty);
367 (*iter2)->syncCache() ;
368 (*iter1)->copyCache(*iter2,kTRUE,setValDirty) ;
383 Bool_t RooAbsCollection::addOwned(RooAbsArg& var, Bool_t silent)
386 if(!_ownCont && (getSize() > 0) && !silent) {
387 coutE(ObjectHandling) << ClassName() <<
"::" << GetName() <<
"::addOwned: can only add to an owned list" << endl;
392 _list.push_back(&var);
393 if (_allRRV && dynamic_cast<RooRealVar*>(&var)==0) {
409 RooAbsArg *RooAbsCollection::addClone(
const RooAbsArg& var, Bool_t silent)
412 if(!_ownCont && (getSize() > 0) && !silent) {
413 coutE(ObjectHandling) << ClassName() <<
"::" << GetName() <<
"::addClone: can only add to an owned list" << endl;
419 auto clone2 =
static_cast<RooAbsArg*
>(var.Clone());
420 if (clone2) _list.push_back(clone2);
421 if (_allRRV && dynamic_cast<const RooRealVar*>(&var)==0) {
435 Bool_t RooAbsCollection::add(
const RooAbsArg& var, Bool_t silent)
438 if(_ownCont && !silent) {
439 coutE(ObjectHandling) << ClassName() <<
"::" << GetName() <<
"::add: cannot add to an owned list" << endl;
444 _list.push_back(const_cast<RooAbsArg*>(&var));
445 if (_allRRV && dynamic_cast<const RooRealVar*>(&var)==0) {
457 Bool_t RooAbsCollection::add(
const RooAbsCollection& list, Bool_t silent)
459 Bool_t result(
false) ;
460 _list.reserve(_list.size() + list._list.size());
462 for (
auto item : list._list) {
463 result |= add(*item,silent);
475 Bool_t RooAbsCollection::addOwned(
const RooAbsCollection& list, Bool_t silent)
477 Bool_t result(
false) ;
478 _list.reserve(_list.size() + list._list.size());
480 for (
auto item : list._list) {
481 result |= addOwned(*item, silent) ;
493 void RooAbsCollection::addClone(
const RooAbsCollection& list, Bool_t silent)
495 _list.reserve(_list.size() + list._list.size());
497 for (
auto item : list._list) {
498 addClone(*item, silent);
508 Bool_t RooAbsCollection::replace(
const RooAbsCollection &other)
512 coutE(ObjectHandling) <<
"RooAbsCollection: cannot replace variables in a copied list" << endl;
517 for (
const auto * arg : other._list) {
519 auto found = find(*arg);
520 if (found) replace(*found,*arg);
533 Bool_t RooAbsCollection::replace(
const RooAbsArg& var1,
const RooAbsArg& var2)
537 coutE(ObjectHandling) <<
"RooAbsCollection: cannot replace variables in a copied list" << endl;
542 const char *name= var1.GetName();
543 auto var1It = std::find(_list.begin(), _list.end(), &var1);
545 if (var1It == _list.end()) {
546 coutE(ObjectHandling) <<
"RooAbsCollection: variable \"" << name <<
"\" is not in the list"
547 <<
" and cannot be replaced" << endl;
553 if (dynamic_cast<RooArgSet*>(
this)) {
554 RooAbsArg *other = find(var2);
555 if(other != 0 && other != &var1) {
556 coutE(ObjectHandling) <<
"RooAbsCollection: cannot replace \"" << name
557 <<
"\" with already existing \"" << var2.GetName() <<
"\"" << endl;
563 *var1It =
const_cast<RooAbsArg*
>(&var2);
565 if (_allRRV && dynamic_cast<const RooRealVar*>(&var2)==0) {
580 Bool_t RooAbsCollection::remove(
const RooAbsArg& var, Bool_t , Bool_t matchByNameOnly)
583 const auto sizeBefore = _list.size();
585 _list.erase(std::remove(_list.begin(), _list.end(), &var), _list.end());
587 if (matchByNameOnly) {
588 const std::string name(var.GetName());
589 auto nameMatch = [&name](
const RooAbsArg* elm) {
590 return elm->GetName() == name;
592 std::set<RooAbsArg*> toBeDeleted;
595 std::for_each(_list.begin(), _list.end(), [&toBeDeleted, nameMatch](RooAbsArg* elm){
596 if (nameMatch(elm)) {
597 toBeDeleted.insert(elm);
602 _list.erase(std::remove_if(_list.begin(), _list.end(), nameMatch), _list.end());
604 for (
auto arg : toBeDeleted)
608 return sizeBefore != _list.size();
617 Bool_t RooAbsCollection::remove(
const RooAbsCollection& list, Bool_t silent, Bool_t matchByNameOnly)
620 auto oldSize = _list.size();
621 for (
auto item : list._list) {
622 remove(*item, silent, matchByNameOnly);
625 return oldSize != _list.size();
635 void RooAbsCollection::removeAll()
652 void RooAbsCollection::setAttribAll(
const Text_t* name, Bool_t value)
654 for (
auto arg : _list) {
655 arg->setAttribute(name, value);
667 RooAbsCollection* RooAbsCollection::selectByAttrib(
const char* name, Bool_t value)
const
669 TString selName(GetName()) ;
670 selName.Append(
"_selection") ;
671 RooAbsCollection *sel = (RooAbsCollection*) create(selName.Data()) ;
674 for (
auto arg : _list) {
675 if (arg->getAttribute(name)==value)
690 RooAbsCollection* RooAbsCollection::selectCommon(
const RooAbsCollection& refColl)
const
693 TString selName(GetName()) ;
694 selName.Append(
"_selection") ;
695 RooAbsCollection *sel = (RooAbsCollection*) create(selName.Data()) ;
698 for (
auto arg : _list) {
699 if (refColl.find(*arg))
713 RooAbsCollection* RooAbsCollection::selectByName(
const char* nameList, Bool_t verbose)
const
716 TString selName(GetName()) ;
717 selName.Append(
"_selection") ;
718 RooAbsCollection *sel = (RooAbsCollection*) create(selName.Data()) ;
720 const size_t bufSize = strlen(nameList) + 1;
721 char* buf =
new char[bufSize] ;
722 strlcpy(buf,nameList,bufSize) ;
723 char* wcExpr = strtok(buf,
",") ;
725 TRegexp rexp(wcExpr,kTRUE) ;
727 cxcoutD(ObjectHandling) <<
"RooAbsCollection::selectByName(" << GetName() <<
") processing expression '" << wcExpr <<
"'" << endl ;
730 RooFIter iter = fwdIterator() ;
732 while((arg=iter.next())) {
733 if (TString(arg->GetName()).Index(rexp)>=0) {
735 cxcoutD(ObjectHandling) <<
"RooAbsCollection::selectByName(" << GetName() <<
") selected element " << arg->GetName() << endl ;
740 wcExpr = strtok(0,
",") ;
753 Bool_t RooAbsCollection::equals(
const RooAbsCollection& otherColl)
const
756 if (getSize() != otherColl.getSize())
return kFALSE ;
759 auto compareByNamePtr = [](
const RooAbsArg * left,
const RooAbsArg * right) {
760 return left->namePtr() == right->namePtr();
763 return std::is_permutation(_list.begin(), _list.end(),
764 otherColl._list.begin(),
774 Bool_t RooAbsCollection::overlaps(
const RooAbsCollection& otherColl)
const
776 for (
auto arg : _list) {
777 if (otherColl.find(*arg)) {
791 RooAbsArg * RooAbsCollection::find(
const char *name)
const
796 decltype(_list)::const_iterator item;
798 if (_list.size() < 10) {
799 auto findByName = [name](
const RooAbsArg * elm){
800 return strcmp(elm->GetName(), name) == 0;
803 item = std::find_if(_list.begin(), _list.end(), findByName);
806 const TNamed* nptr= RooNameReg::known(name);
807 if (!nptr)
return nullptr;
809 auto findByNamePtr = [nptr](
const RooAbsArg* elm) {
810 return nptr == elm->namePtr();
813 item = std::find_if(_list.begin(), _list.end(), findByNamePtr);
816 return item != _list.end() ? *item :
nullptr;
825 RooAbsArg * RooAbsCollection::find(
const RooAbsArg& arg)
const
827 const auto nptr = arg.namePtr();
828 auto findByNamePtr = [nptr](
const RooAbsArg * listItem) {
829 return nptr == listItem->namePtr();
832 auto item = std::find_if(_list.begin(), _list.end(), findByNamePtr);
834 return item != _list.end() ? *item :
nullptr;
842 string RooAbsCollection::contentsString()
const
845 for (
auto arg : _list) {
846 retVal += arg->GetName();
850 retVal.erase(retVal.end()-1);
860 void RooAbsCollection::printName(ostream& os)
const
870 void RooAbsCollection::printTitle(ostream& os)
const
880 void RooAbsCollection::printClassName(ostream& os)
const
882 os << IsA()->GetName() ;
893 Int_t RooAbsCollection::defaultPrintContents(Option_t* opt)
const
895 if (opt && TString(opt)==
"I") {
898 if (opt && TString(opt).Contains(
"v")) {
899 return kAddress|kName|kArgs|kClassName|kValue|kTitle|kExtras ;
901 return kName|kClassName|kValue ;
912 void RooAbsCollection::printValue(ostream& os)
const
914 Bool_t first2(kTRUE) ;
916 for (
auto arg : _list) {
922 if (arg->IsA()->InheritsFrom(RooStringVar::Class())) {
923 os <<
'\'' << ((RooStringVar *)arg)->getVal() <<
'\'';
925 os << arg->GetName();
937 void RooAbsCollection::printMultiline(ostream&os, Int_t contents, Bool_t , TString indent)
const
939 if (TString(GetName()).Length()>0 && (contents&kCollectionHeader)) {
940 os << indent << ClassName() <<
"::" << GetName() <<
":" << (_ownCont?
" (Owning contents)":
"") << endl;
943 TString deeper(indent);
947 Int_t maxNameLen(1) ;
948 Int_t nameFieldLengthSaved = RooPrintable::_nameLength ;
949 if (nameFieldLengthSaved==0) {
950 for (
auto next : _list) {
951 Int_t len = strlen(next->GetName()) ;
952 if (len>maxNameLen) maxNameLen = len ;
954 RooPrintable::nameFieldLength(maxNameLen+1) ;
957 unsigned int idx = 0;
958 for (
auto next : _list) {
959 os << indent << std::setw(3) << ++idx <<
") ";
960 next->printStream(os,contents,kSingleLine,
"");
964 RooPrintable::nameFieldLength(nameFieldLengthSaved) ;
972 void RooAbsCollection::dump()
const
974 for (
auto arg : _list) {
975 cout << arg <<
" " << arg->IsA()->GetName() <<
"::" << arg->GetName() <<
" (" << arg->GetTitle() <<
")" << endl ;
1014 void RooAbsCollection::printLatex(
const RooCmdArg& arg1,
const RooCmdArg& arg2,
1015 const RooCmdArg& arg3,
const RooCmdArg& arg4,
1016 const RooCmdArg& arg5,
const RooCmdArg& arg6,
1017 const RooCmdArg& arg7,
const RooCmdArg& arg8)
const
1022 RooCmdConfig pc(
"RooAbsCollection::printLatex()") ;
1023 pc.defineInt(
"ncol",
"Columns",0,1) ;
1024 pc.defineString(
"outputFile",
"OutputFile",0,
"") ;
1025 pc.defineString(
"format",
"Format",0,
"NEYVU") ;
1026 pc.defineInt(
"sigDigit",
"Format",0,1) ;
1027 pc.defineObject(
"siblings",
"Sibling",0,0,kTRUE) ;
1028 pc.defineInt(
"dummy",
"FormatArgs",0,0) ;
1029 pc.defineMutex(
"Format",
"FormatArgs") ;
1032 RooLinkedList cmdList;
1033 cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
1034 cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
1035 cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
1036 cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
1039 pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
1040 if (!pc.ok(kTRUE)) {
1044 const char* outFile = pc.getString(
"outputFile") ;
1045 if (outFile && strlen(outFile)) {
1046 std::ofstream ofs(outFile) ;
1047 if (pc.hasProcessed(
"FormatArgs")) {
1048 RooCmdArg* formatCmd =
static_cast<RooCmdArg*
>(cmdList.FindObject(
"FormatArgs")) ;
1049 formatCmd->addArg(RooFit::LatexTableStyle()) ;
1050 printLatex(ofs,pc.getInt(
"ncol"),0,0,pc.getObjectList(
"siblings"),formatCmd) ;
1052 printLatex(ofs,pc.getInt(
"ncol"),pc.getString(
"format"),pc.getInt(
"sigDigit"),pc.getObjectList(
"siblings")) ;
1055 if (pc.hasProcessed(
"FormatArgs")) {
1056 RooCmdArg* formatCmd =
static_cast<RooCmdArg*
>(cmdList.FindObject(
"FormatArgs")) ;
1057 formatCmd->addArg(RooFit::LatexTableStyle()) ;
1058 printLatex(cout,pc.getInt(
"ncol"),0,0,pc.getObjectList(
"siblings"),formatCmd) ;
1060 printLatex(cout,pc.getInt(
"ncol"),pc.getString(
"format"),pc.getInt(
"sigDigit"),pc.getObjectList(
"siblings")) ;
1071 void RooAbsCollection::printLatex(ostream& ofs, Int_t ncol,
const char* option, Int_t sigDigit,
const RooLinkedList& siblingList,
const RooCmdArg* formatCmd)
const
1074 Int_t nrow = (Int_t) (getSize() / ncol + 0.99) ;
1079 RooCmdArg sibFormatCmd ;
1081 sibOption = option ;
1082 sibOption.ReplaceAll(
"N",
"") ;
1083 sibOption.ReplaceAll(
"n",
"") ;
1085 sibFormatCmd = *formatCmd ;
1086 TString tmp = formatCmd->_s[0] ;
1087 tmp.ReplaceAll(
"N",
"") ;
1088 tmp.ReplaceAll(
"n",
"") ;
1089 static char buf[100] ;
1090 strlcpy(buf,tmp.Data(),100) ;
1091 sibFormatCmd._s[0] = buf ;
1096 RooLinkedList listList ;
1097 listList.Add((RooAbsArg*)
this) ;
1098 RooFIter sIter = siblingList.fwdIterator() ;
1099 RooAbsCollection* col ;
1100 while((col=(RooAbsCollection*)sIter.next())) {
1104 RooLinkedList listListRRV ;
1107 RooFIter lIter = listList.fwdIterator() ;
1108 RooArgList* prevList = 0 ;
1109 while((col=(RooAbsCollection*)lIter.next())) {
1110 RooArgList* list =
new RooArgList ;
1111 RooFIter iter = col->fwdIterator() ;
1113 while((arg=iter.next())) {
1115 RooRealVar* rrv =
dynamic_cast<RooRealVar*
>(arg) ;
1119 coutW(InputArguments) <<
"RooAbsCollection::printLatex: can only print RooRealVar in LateX, skipping non-RooRealVar object named "
1120 << arg->GetName() << endl ;
1122 if (prevList && TString(rrv->GetName()).CompareTo(prevList->at(list->getSize()-1)->GetName())) {
1123 coutW(InputArguments) <<
"RooAbsCollection::printLatex: WARNING: naming and/or ordering of sibling list is different" << endl ;
1126 listListRRV.Add(list) ;
1127 if (prevList && list->getSize() != prevList->getSize()) {
1128 coutW(InputArguments) <<
"RooAbsCollection::printLatex: ERROR: sibling list(s) must have same length as self" << endl ;
1130 listListRRV.Delete() ;
1137 Int_t nlist = listListRRV.GetSize() ;
1138 TString subheader =
"l" ;
1139 for (k=0 ; k<nlist ; k++) subheader +=
"c" ;
1141 TString header =
"\\begin{tabular}{" ;
1142 for (j=0 ; j<ncol ; j++) {
1143 if (j>0) header +=
"|" ;
1144 header += subheader ;
1147 ofs << header << endl ;
1151 for (i=0 ; i<nrow ; i++) {
1152 for (j=0 ; j<ncol ; j++) {
1153 for (k=0 ; k<nlist ; k++) {
1154 RooRealVar* par = (RooRealVar*) ((RooArgList*)listListRRV.At(k))->at(i+j*nrow) ;
1157 TString* tmp = par->format(sigDigit,(k==0)?option:sibOption.Data()) ;
1161 TString* tmp = par->format((k==0)?*formatCmd:sibFormatCmd) ;
1166 if (!(j==ncol-1 && k==nlist-1)) {
1171 ofs <<
"\\\\" << endl ;
1174 ofs <<
"\\end{tabular}" << endl ;
1175 listListRRV.Delete() ;
1185 Bool_t RooAbsCollection::allInRange(
const char* rangeSpec)
const
1187 if (!rangeSpec)
return kTRUE ;
1190 vector<string> cutVec ;
1191 if (rangeSpec && strlen(rangeSpec)>0) {
1192 if (strchr(rangeSpec,
',')==0) {
1193 cutVec.push_back(rangeSpec) ;
1195 const size_t bufSize = strlen(rangeSpec)+1;
1196 char* buf =
new char[bufSize] ;
1197 strlcpy(buf,rangeSpec,bufSize) ;
1198 const char* oneRange = strtok(buf,
",") ;
1200 cutVec.push_back(oneRange) ;
1201 oneRange = strtok(0,
",") ;
1208 Bool_t selectByRange = kTRUE ;
1209 for (
auto arg : _list) {
1210 Bool_t selectThisArg = kFALSE ;
1212 for (icut=0 ; icut<cutVec.size() ; icut++) {
1213 if (arg->inRange(cutVec[icut].c_str())) {
1214 selectThisArg = kTRUE ;
1218 if (!selectThisArg) {
1219 selectByRange = kFALSE ;
1224 return selectByRange ;
1231 void RooAbsCollection::makeStructureTag()
1238 void RooAbsCollection::makeTypedStructureTag()
1246 void RooAbsCollection::RecursiveRemove(TObject *obj)
1248 if (obj && obj->InheritsFrom(RooAbsArg::Class()))
remove(*(RooAbsArg*)obj,
false,
false);
1254 void RooAbsCollection::sort(Bool_t reverse) {
1259 const auto cmpReverse = [](
const RooAbsArg * l,
const RooAbsArg * r) {
1260 return strcmp(l->GetName(), r->GetName()) > 0;
1263 std::sort(_list.begin(), _list.end(), cmpReverse);
1266 const auto cmp = [](
const RooAbsArg * l,
const RooAbsArg * r) {
1267 return strcmp(l->GetName(), r->GetName()) < 0;
1270 std::sort(_list.begin(), _list.end(), cmp);
1277 std::unique_ptr<RooAbsCollection::LegacyIterator_t> RooAbsCollection::makeLegacyIterator (
bool forward)
const {
1279 ccoutE(DataHandling) <<
"The legacy RooFit collection iterators don't support reverse iterations, any more. "
1280 <<
"Use begin() and end()" << endl;
1281 return std::make_unique<LegacyIterator_t>(_list);