51 ClassImp(RooAbsCategory);
58 RooAbsCategory::RooAbsCategory(
const char *name,
const char *title) :
59 RooAbsArg(name,title), _byteValue(0), _value(
"NULL",0), _treeVar(kFALSE)
70 RooAbsCategory::RooAbsCategory(
const RooAbsCategory& other,
const char* name) :
71 RooAbsArg(other,name), _byteValue(0), _value(other._value), _treeVar(other._treeVar)
73 for (
const auto cat : other._types) {
74 _types.push_back(
new RooCatType(*cat));
86 RooAbsCategory::~RooAbsCategory()
96 Int_t RooAbsCategory::getIndex()
const
98 if (isValueDirty() || isShapeDirty()) {
99 _value = traceEval() ;
105 return _value.getVal() ;
113 const char* RooAbsCategory::getLabel()
const
115 if (isValueDirty() || isShapeDirty()) {
116 _value = traceEval() ;
122 const char* ret = _value.GetName() ;
125 _value.SetName(lookupType(_value.getVal())->GetName()) ;
127 return _value.GetName() ;
135 RooCatType RooAbsCategory::traceEval()
const
137 RooCatType value = evaluate() ;
140 if (!isValid(value)) {
144 traceEvalHook(value) ;
153 Bool_t RooAbsCategory::operator==(Int_t index)
const
155 return (index==getIndex()) ;
163 Bool_t RooAbsCategory::operator==(
const char* label)
const
165 return strcmp(label, getLabel()) == 0;
174 Bool_t RooAbsCategory::operator==(
const RooAbsArg& other)
176 const RooAbsCategory* otherCat =
dynamic_cast<const RooAbsCategory*
>(&other) ;
177 return otherCat ? operator==(otherCat->getIndex()) : kFALSE ;
183 Bool_t RooAbsCategory::isIdentical(
const RooAbsArg& other, Bool_t assumeSameType)
185 if (!assumeSameType) {
186 const RooAbsCategory* otherCat =
dynamic_cast<const RooAbsCategory*
>(&other) ;
187 return otherCat ? operator==(otherCat->getIndex()) : kFALSE ;
189 return getIndex()==((RooAbsCategory&)other).getIndex() ;
199 Bool_t RooAbsCategory::isValidIndex(Int_t index)
const
201 return lookupType(index,kFALSE)?kTRUE:kFALSE ;
209 Bool_t RooAbsCategory::isValidLabel(
const char* label)
const
211 return lookupType(label)?kTRUE:kFALSE ;
220 const RooCatType* RooAbsCategory::defineType(
const char* label)
224 while(lookupType(++index,kFALSE)) ;
227 return defineType(label,index) ;
235 const RooCatType* RooAbsCategory::defineTypeUnchecked(
const char* label, Int_t index)
237 _types.push_back(
new RooCatType(label, index));
239 if (_types.size() == 1) _value = *_types.back();
242 return _types.back();
250 const RooCatType* RooAbsCategory::defineType(
const char* label, Int_t index)
252 if (isValidIndex(index)) {
253 coutE(InputArguments) <<
"RooAbsCategory::defineType(" << GetName() <<
"): index "
254 << index <<
" already assigned" << endl ;
258 if (isValidLabel(label)) {
259 coutE(InputArguments) <<
"RooAbsCategory::defineType(" << GetName() <<
"): label "
260 << label <<
" already assigned or not allowed" << endl ;
264 return defineTypeUnchecked(label,index) ;
272 void RooAbsCategory::clearTypes()
274 for (
auto cat : _types)
277 _value = RooCatType(
"",0) ;
286 const RooCatType* RooAbsCategory::lookupType(
const RooCatType &other, Bool_t printError)
const
288 for (
const auto type : _types) {
289 if (*type == other)
return type;
293 coutE(InputArguments) << ClassName() <<
"::" << GetName() <<
":lookupType: no match for ";
294 if (dologE(InputArguments)) {
295 other.printStream(ccoutE(InputArguments),kName|kValue,kSingleLine);
306 const RooCatType* RooAbsCategory::lookupType(Int_t index, Bool_t printError)
const
308 for (
const auto type : _types) {
309 if(*type == index)
return type;
312 coutE(InputArguments) << ClassName() <<
"::" << GetName() <<
":lookupType: no match for index "
323 const RooCatType* RooAbsCategory::lookupType(
const char* label, Bool_t printError)
const
325 for (
const auto type : _types) {
326 if(*type == label)
return type;
331 Int_t idx=strtol(label,&endptr,10) ;
332 if (endptr==label+strlen(label)) {
333 for (
const auto type : _types) {
334 if(*type == idx)
return type;
339 coutE(InputArguments) << ClassName() <<
"::" << GetName() <<
":lookupType: no match for label "
350 Bool_t RooAbsCategory::isValid()
const
352 return isValid(_value) ;
360 Bool_t RooAbsCategory::isValid(
const RooCatType& value)
const
362 return isValidIndex(value.getVal()) ;
370 Roo1DTable* RooAbsCategory::createTable(
const char *label)
const
372 return new Roo1DTable(GetName(),label,*
this) ;
380 Bool_t RooAbsCategory::readFromStream(istream&, Bool_t, Bool_t)
390 void RooAbsCategory::writeToStream(ostream& os, Bool_t )
const
400 void RooAbsCategory::printValue(ostream& os)
const
402 os << getLabel() <<
"(idx = " << getIndex() <<
")" << endl ;
413 void RooAbsCategory::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent)
const
415 RooAbsArg::printMultiline(os,contents,verbose,indent);
417 os << indent <<
"--- RooAbsCategory ---" << endl;
418 if (_types.empty()) {
419 os << indent <<
" ** No values defined **" << endl;
422 os << indent <<
" Value is \"" << getLabel() <<
"\" (" << getIndex() <<
")" << endl;
423 os << indent <<
" Has the following possible values:" << endl;
425 for (
const auto type : _types) {
427 type->printStream(os,kName|kValue,kSingleLine,indent);
436 void RooAbsCategory::attachToVStore(RooVectorDataStore& vstore)
438 RooVectorDataStore::CatVector* cv = vstore.addCategory(
this) ;
439 cv->setBuffer(&_value) ;
451 void RooAbsCategory::attachToTree(TTree& t, Int_t bufSize)
454 TString cleanName(cleanBranchName()) ;
455 TBranch* branch = t.GetBranch(cleanName) ;
458 TString typeName(((TLeaf*)branch->GetListOfLeaves()->At(0))->GetTypeName()) ;
459 if (!typeName.CompareTo(
"Int_t")) {
462 coutI(DataHandling) <<
"RooAbsCategory::attachToTree(" << GetName() <<
") TTree branch " << GetName()
463 <<
" will be interpreted as category index" << endl ;
465 t.SetBranchAddress(cleanName,&((Int_t&)_value._value)) ;
466 setAttribute(
"INTIDXONLY_TREE_BRANCH",kTRUE) ;
469 }
else if (!typeName.CompareTo(
"UChar_t")) {
470 coutI(DataHandling) <<
"RooAbsReal::attachToTree(" << GetName() <<
") TTree UChar_t branch " << GetName()
471 <<
" will be interpreted as category index" << endl ;
472 t.SetBranchAddress(cleanName,&_byteValue) ;
473 setAttribute(
"UCHARIDXONLY_TREE_BRANCH",kTRUE) ;
478 if (branch->GetCompressionLevel()<0) {
479 cxcoutD(DataHandling) <<
"RooAbsCategory::attachToTree(" << GetName() <<
") Fixing compression level of branch " << GetName() << endl ;
480 branch->SetCompressionLevel(ROOT::RCompressionSetting::EDefaults::kUseGlobal % 100) ;
485 TString idxName(cleanName) ;
486 TString lblName(cleanName) ;
487 idxName.Append(
"_idx") ;
488 lblName.Append(
"_lbl") ;
491 if ((branch = t.GetBranch(idxName))) {
493 t.SetBranchAddress(idxName,&((Int_t&)_value._value)) ;
494 if (branch->GetCompressionLevel()<0) {
495 cxcoutD(Contents) <<
"RooAbsCategory::attachToTree(" << GetName() <<
") Fixing compression level of branch " << idxName << endl ;
496 branch->SetCompressionLevel(ROOT::RCompressionSetting::EDefaults::kUseGlobal % 100) ;
500 TString format(idxName);
502 void* ptr = &(_value._value) ;
503 branch = t.Branch(idxName, ptr, (
const Text_t*)format, bufSize);
504 branch->SetCompressionLevel(ROOT::RCompressionSetting::EDefaults::kUseGlobal % 100) ;
508 if ((branch = t.GetBranch(lblName))) {
510 t.SetBranchAddress(lblName,_value._label) ;
511 if (branch->GetCompressionLevel()<0) {
512 cxcoutD(DataHandling) <<
"RooAbsCategory::attachToTree(" << GetName() <<
") Fixing compression level of branch " << lblName << endl ;
513 branch->SetCompressionLevel(ROOT::RCompressionSetting::EDefaults::kUseGlobal % 100) ;
517 TString format(lblName);
519 void* ptr = _value._label ;
520 branch = t.Branch(lblName, ptr, (
const Text_t*)format, bufSize);
521 branch->SetCompressionLevel(ROOT::RCompressionSetting::EDefaults::kUseGlobal % 100) ;
531 void RooAbsCategory::fillTreeBranch(TTree& t)
533 TString idxName(GetName()) ;
534 TString lblName(GetName()) ;
535 idxName.Append(
"_idx") ;
536 lblName.Append(
"_lbl") ;
539 TBranch* idxBranch = t.GetBranch(idxName) ;
540 TBranch* lblBranch = t.GetBranch(lblName) ;
541 if (!idxBranch||!lblBranch) {
542 coutF(DataHandling) <<
"RooAbsCategory::fillTreeBranch(" << GetName() <<
") ERROR: not attached to tree" << endl ;
555 void RooAbsCategory::setTreeBranchStatus(TTree& t, Bool_t active)
557 TBranch* branch = t.GetBranch(Form(
"%s_idx",GetName())) ;
559 t.SetBranchStatus(Form(
"%s_idx",GetName()),active?1:0) ;
560 t.SetBranchStatus(Form(
"%s_lbl",GetName()),active?1:0) ;
569 void RooAbsCategory::syncCache(
const RooArgSet*)
582 void RooAbsCategory::copyCache(
const RooAbsArg *source, Bool_t , Bool_t setValDirty)
584 RooAbsCategory *other =
static_cast<RooAbsCategory *
>(
const_cast<RooAbsArg *
>(source));
587 _value = other->_value;
589 if (source->getAttribute(
"INTIDXONLY_TREE_BRANCH")) {
591 const RooCatType *type = lookupType(other->_value._value);
595 coutE(DataHandling) <<
"RooAbsCategory::copyCache(" << GetName() <<
") ERROR: index of source arg "
596 << source->GetName() <<
" is invalid (" << other->_value._value
597 <<
"), value not updated" << endl;
599 }
else if (source->getAttribute(
"UCHARIDXONLY_TREE_BRANCH")) {
601 Int_t tmp = other->_byteValue;
602 const RooCatType *type = lookupType(tmp);
606 coutE(DataHandling) <<
"RooAbsCategory::copyCache(" << GetName() <<
") ERROR: index of source arg "
607 << source->GetName() <<
" is invalid (" << tmp <<
"), value not updated" << endl;
621 const RooCatType* RooAbsCategory::getOrdinal(UInt_t n,
const char* )
const
623 return _types.size() > n ? _types[n] :
nullptr;
631 RooAbsArg *RooAbsCategory::createFundamental(
const char* newname)
const
634 RooCategory *fund=
new RooCategory(newname?newname:GetName(),GetTitle()) ;
637 for (
const auto type : _types) {
638 ((RooAbsCategory*)fund)->defineType(type->GetName(), type->getVal());
649 Bool_t RooAbsCategory::isSignType(Bool_t mustHaveZero)
const
651 if (numTypes()>3||numTypes()<2)
return kFALSE ;
652 if (mustHaveZero&&numTypes()!=3)
return kFALSE ;
655 for (
const auto type : _types) {
656 if (abs(type->getVal())>1) ret=kFALSE ;