Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooSuperCategory.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * @(#)root/roofitcore:$Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 /**
18 \file RooSuperCategory.cxx
19 \class RooSuperCategory
20 \ingroup Roofitcore
21 
22 RooSuperCategory can join several RooAbsCategoryLValue objects into
23 a single category. The states of the super category consist of all the permutations
24 of the input categories. The super category is an lvalue and requires that
25 all input categories are lvalues as well. This is because a modification
26 of its state will back propagate into a modification of its input categories.
27 To define a joined category of multiple non-lvalue categories,
28 use the class RooMultiCategory.
29 RooSuperCategory states are automatically defined and updated whenever an input
30 category modifies its list of states.
31 **/
32 
33 #include "RooFit.h"
34 
35 #include "Riostream.h"
36 #include "Riostream.h"
37 #include <stdlib.h>
38 #include "TString.h"
39 #include "TClass.h"
40 #include "RooSuperCategory.h"
41 #include "RooStreamParser.h"
42 #include "RooArgSet.h"
43 #include "RooMultiCatIter.h"
44 #include "RooAbsCategoryLValue.h"
45 #include "RooMsgService.h"
46 
47 using namespace std;
48 
49 ClassImp(RooSuperCategory);
50 ;
51 
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 /// Construct a lvalue product of the given set of input RooAbsCategoryLValues in 'inInputCatList'
55 /// The state names of this product category are {S1;S2,S3,...Sn} where Si are the state names
56 /// of the input categories. A RooSuperCategory is an lvalue.
57 
58 RooSuperCategory::RooSuperCategory(const char *name, const char *title, const RooArgSet& inInputCatList) :
59  RooAbsCategoryLValue(name, title), _catSet("input","Input category set",this,kTRUE,kTRUE)
60 {
61  // Copy category list
62  TIterator* iter = inInputCatList.createIterator() ;
63  RooAbsArg* arg ;
64  while ((arg=(RooAbsArg*)iter->Next())) {
65  if (!arg->IsA()->InheritsFrom(RooAbsCategoryLValue::Class())) {
66  coutE(InputArguments) << "RooSuperCategory::RooSuperCategory(" << GetName() << "): input category " << arg->GetName()
67  << " is not an lvalue" << endl ;
68  }
69  _catSet.add(*arg) ;
70  }
71  delete iter ;
72 
73  updateIndexList() ;
74 }
75 
76 
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// Copy constructor
80 
81 RooSuperCategory::RooSuperCategory(const RooSuperCategory& other, const char *name) :
82  RooAbsCategoryLValue(other,name), _catSet("input",this,other._catSet)
83 {
84  updateIndexList() ;
85  setIndex(other.getIndex()) ;
86 }
87 
88 
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Destructor
92 
93 RooSuperCategory::~RooSuperCategory()
94 {
95 
96 }
97 
98 
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Make an iterator over all state permutations of
102 /// the input categories of this supercategory
103 
104 TIterator* RooSuperCategory::MakeIterator() const
105 {
106  return new RooMultiCatIter(_catSet) ;
107 }
108 
109 
110 
111 ////////////////////////////////////////////////////////////////////////////////
112 /// Update the list of possible states of this super category
113 
114 void RooSuperCategory::updateIndexList()
115 {
116  clearTypes() ;
117 
118  RooMultiCatIter mcIter(_catSet) ;
119  TObjString* obj ;
120  Int_t i(0) ;
121  while((obj = (TObjString*) mcIter.Next())) {
122  // Register composite label
123  defineTypeUnchecked(obj->String(),i++) ;
124  }
125 
126  // Renumbering will invalidate cache
127  setValueDirty() ;
128 }
129 
130 
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Return the name of the current state,
134 /// constructed from the state names of the input categories
135 
136 TString RooSuperCategory::currentLabel() const
137 {
138 
139  // Construct composite label name
140  TString label ;
141  Bool_t first(kTRUE) ;
142  for (const auto c : _catSet) {
143  auto cat = static_cast<RooAbsCategory*>(c);
144 
145  label.Append(first?"{":";") ;
146  label.Append(cat->getLabel()) ;
147  first=kFALSE ;
148  }
149  label.Append("}") ;
150 
151  return label ;
152 }
153 
154 
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Calculate and return the current value
158 
159 RooCatType RooSuperCategory::evaluate() const
160 {
161  if (isShapeDirty()) {
162  const_cast<RooSuperCategory*>(this)->updateIndexList() ;
163  }
164  const RooCatType* ret = lookupType(currentLabel(),kTRUE) ;
165  if (!ret) {
166  coutE(Eval) << "RooSuperCat::evaluate(" << this << ") error: current state not defined: '" << currentLabel() << "'" << endl ;
167  printStream(ccoutE(Eval),0,kVerbose) ;
168  return RooCatType() ;
169  }
170  return *ret ;
171 }
172 
173 
174 
175 ////////////////////////////////////////////////////////////////////////////////
176 /// Set the value of the super category by specifying the state index code
177 /// by setting the states of the corresponding input category lvalues
178 
179 Bool_t RooSuperCategory::setIndex(Int_t index, Bool_t /*printError*/)
180 {
181  const RooCatType* type = lookupType(index,kTRUE) ;
182  if (!type) return kTRUE ;
183  return setType(type) ;
184 }
185 
186 
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Set the value of the super category by specifying the state name
190 /// by setting the state names of the corresponding input category lvalues
191 
192 Bool_t RooSuperCategory::setLabel(const char* label, Bool_t /*printError*/)
193 {
194  const RooCatType* type = lookupType(label,kTRUE) ;
195  if (!type) return kTRUE ;
196  return setType(type) ;
197 }
198 
199 
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 /// Set the value of the super category by specifying the state object
203 /// by setting the state names of the corresponding input category lvalues
204 
205 Bool_t RooSuperCategory::setType(const RooCatType* type, Bool_t /*printError*/)
206 {
207  char buf[1024] ;
208  strlcpy(buf,type->GetName(),1024) ;
209 
210  Bool_t error(kFALSE) ;
211 
212  // Parse composite label and set label of components to their values
213  char* ptr=buf+1 ;
214  char* token = ptr ;
215  for (const auto c : _catSet) {
216  auto arg = static_cast<RooAbsCategoryLValue*>(c);
217 
218  // Delimit name token for this category
219  if (*ptr=='{') {
220  // Token is composite itself, terminate at matching '}'
221  Int_t nBrak(1) ;
222  while(*(++ptr)) {
223  if (nBrak==0) {
224  *ptr = 0 ;
225  break ;
226  }
227  if (*ptr=='{') {
228  nBrak++ ;
229  } else if (*ptr=='}') {
230  nBrak-- ;
231  }
232  }
233  } else {
234  // Simple token, terminate at next semi-colon
235  ptr = strtok(ptr,";}") ;
236  ptr += strlen(ptr) ;
237  }
238 
239  error |= arg->setLabel(token) ;
240  token = ++ptr ;
241  }
242 
243  return error ;
244 }
245 
246 
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Print the state of this object to the specified output stream.
250 
251 void RooSuperCategory::printMultiline(ostream& os, Int_t content, Bool_t verbose, TString indent) const
252 {
253  RooAbsCategory::printMultiline(os,content,verbose,indent) ;
254 
255  if (verbose) {
256  os << indent << "--- RooSuperCategory ---" << endl;
257  os << indent << " Input category list:" << endl ;
258  TString moreIndent(indent) ;
259  os << moreIndent << _catSet << endl ;
260  }
261 }
262 
263 
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Read object contents from given stream
267 
268 Bool_t RooSuperCategory::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/)
269 {
270  return kTRUE ;
271 }
272 
273 
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 /// Write object contents to given stream
277 
278 void RooSuperCategory::writeToStream(ostream& os, Bool_t compact) const
279 {
280  RooAbsCategory::writeToStream(os,compact) ;
281 }
282 
283 
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// Return true of all of the input category states are in the given range
287 
288 Bool_t RooSuperCategory::inRange(const char* rangeName) const
289 {
290  for (const auto c : _catSet) {
291  auto cat = static_cast<RooAbsCategoryLValue*>(c);
292  if (!cat->inRange(rangeName)) {
293  return kFALSE ;
294  }
295  }
296  return kTRUE ;
297 }
298 
299 
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Return true if any of the input categories has a range
303 /// named 'rangeName'
304 
305 Bool_t RooSuperCategory::hasRange(const char* rangeName) const
306 {
307  for (const auto c : _catSet) {
308  auto cat = static_cast<RooAbsCategoryLValue*>(c);
309  if (cat->hasRange(rangeName)) return kTRUE ;
310  }
311 
312  return kFALSE ;
313 }