ROOT  6.06/09
Reference Guide
RooMappedCategory.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 // -- CLASS DESCRIPTION [CAT] --
18 // RooMappedCategory provides a category-to-category mapping defined
19 // by pattern matching on their state labels
20 //
21 // The mapping function consists of a series of wild card regular expressions.
22 // Each expression is matched to the input categories state labels, and an associated
23 // output state label.
24 
25 #include <cstdio>
26 #include <memory>
27 #include <cstdlib>
28 
29 #include "RooFit.h"
30 
31 #include "Riostream.h"
32 #include "TString.h"
33 #include "RooMappedCategory.h"
34 #include "RooStreamParser.h"
35 #include "RooMsgService.h"
36 #include "TBuffer.h"
37 #include "TString.h"
38 #include "RooAbsCache.h"
39 
42 
43 class RooMappedCategoryCache : public RooAbsCache {
44  public:
45  RooMappedCategoryCache(RooAbsArg* owner = 0) : RooAbsCache(owner)
46  { initialise(); }
47  RooMappedCategoryCache(const RooAbsCache& other, RooAbsArg* owner = 0) :
48  RooAbsCache(other, owner)
49  { initialise(); }
50 
51  // look up our parent's output based on our parent's input category index
52  const RooCatType* lookup(Int_t idx) const
53  { return _map[idx]; }
54 
55  virtual void wireCache()
56  { _map.clear(); initialise(); }
57 
58  virtual Bool_t redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, Bool_t /*nameChange*/, Bool_t /*isRecursive*/)
59  { _map.clear(); initialise(); return kFALSE; }
60 
61  private:
62  mutable std::map<Int_t, const RooCatType*> _map;
63 
64  // pre-map categories of input category on something easily searchable
65  // like the index (not the name!)
66  void initialise()
67  {
68  const RooMappedCategory& parent = *static_cast<const RooMappedCategory*>(_owner);
69  std::unique_ptr<TIterator> tit(static_cast<const RooAbsCategory&>(
70  parent._inputCat.arg()).typeIterator());
71  for (const RooCatType* inCat = static_cast<const RooCatType*>(tit->Next());
72  inCat; inCat = static_cast<const RooCatType*>(tit->Next())) {
73  const char* inKey = inCat->GetName();
74  // Scan array of regexps
75  bool found = false;
76  for (std::map<std::string, RooMappedCategory::Entry>::const_iterator
77  iter = parent._mapArray.begin(),
78  end = parent._mapArray.end(); end != iter; ++iter) {
79  if (iter->second.match(inKey)) {
80  found = true;
81  _map[inCat->getVal()] = &(iter->second.outCat());
82  break;
83  }
84  }
85  if (!found) _map[inCat->getVal()] = parent._defCat;
86  }
87  }
88 };
89 
90 RooMappedCategory::RooMappedCategory(const char *name, const char *title, RooAbsCategory& inputCat, const char* defOut, Int_t defOutIdx) :
91  RooAbsCategory(name, title), _inputCat("input","Input category",this,inputCat),
92  _mapcache(0)
93 {
94  // Constructor with input category and name of default output state, which is assigned
95  // to all input category states that do not follow any mapping rule.
96  if (defOutIdx==NoCatIdx) {
97  _defCat = (RooCatType*) defineType(defOut) ;
98  } else {
99  _defCat = (RooCatType*) defineType(defOut,defOutIdx) ;
100  }
101 }
102 
103 
105  RooAbsCategory(other,name), _inputCat("input",this,other._inputCat), _mapArray(other._mapArray),
106  _mapcache(0)
107 {
108  _defCat = (RooCatType*) lookupType(other._defCat->GetName()) ;
109 }
110 
111 
112 
114 {
115  // Destructor
116  delete _mapcache;
117 }
118 
119 
120 
121 Bool_t RooMappedCategory::map(const char* inKeyRegExp, const char* outKey, Int_t outIdx)
122 {
123  // Add mapping rule: any input category state label matching the 'inKeyRegExp'
124  // wildcard expression will be mapped to an output state with name 'outKey'
125  //
126  // Rules are evaluated in the order they were added. In case an input state
127  // matches more than one rule, the first rules output state will be assigned
128 
129  if (!inKeyRegExp || !outKey) return kTRUE ;
130 
131  // Check if pattern is already registered
132  if (_mapArray.find(inKeyRegExp)!=_mapArray.end()) {
133  coutE(InputArguments) << "RooMappedCategory::map(" << GetName() << "): ERROR expression "
134  << inKeyRegExp << " already mapped" << std::endl ;
135  return kTRUE ;
136  }
137 
138  // Check if output type exists, if not register
139  const RooCatType* outType = lookupType(outKey) ;
140  if (!outType) {
141  if (outIdx==NoCatIdx) {
142  outType = defineType(outKey) ;
143  } else {
144  outType = defineType(outKey,outIdx) ;
145  }
146  }
147  if (!outType) {
148  coutE(InputArguments) << "RooMappedCategory::map(" << GetName()
149  << "): ERROR, unable to output type " << outKey << std::endl ;
150  return kTRUE ;
151  }
152 
153  // Create new map entry ;
154  Entry e(inKeyRegExp,outType) ;
155  if (!e.ok()) {
156  coutE(InputArguments) << "RooMappedCategory::map(" << GetName()
157  << "): ERROR, expression " << inKeyRegExp << " didn't compile" << std::endl ;
158  return kTRUE ;
159  }
160 
161  _mapArray[inKeyRegExp] = e ;
162  return kFALSE ;
163 }
164 
165 
166 
168 {
169  const RooMappedCategoryCache* cache = getOrCreateCache();
170  return *(cache->lookup(Int_t(_inputCat)));
171 }
172 
174 {
176  const_cast<RooMappedCategory*>(this));
177  return _mapcache;
178 }
179 
180 void RooMappedCategory::printMultiline(std::ostream& os, Int_t content, Bool_t verbose, TString indent) const
181 {
182  // Print info about this mapped category to the specified stream. In addition to the info
183  // from RooAbsCategory::printStream() we add:
184  //
185  // Standard : input category
186  // Shape : default value
187  // Verbose : list of mapping rules
188 
189  RooAbsCategory::printMultiline(os,content,verbose,indent);
190 
191  if (verbose) {
192  os << indent << "--- RooMappedCategory ---" << std::endl
193  << indent << " Maps from " ;
195 
196  os << indent << " Default value is ";
198 
199  os << indent << " Mapping rules:" << std::endl;
200  for (std::map<std::string,Entry>::const_iterator iter = _mapArray.begin() ; iter!=_mapArray.end() ; iter++) {
201  os << indent << " " << iter->first << " -> " << iter->second.outCat().GetName() << std::endl ;
202  }
203  }
204 }
205 
206 
207 Bool_t RooMappedCategory::readFromStream(std::istream& is, Bool_t compact, Bool_t /*verbose*/)
208 {
209  // Read object contents from given stream
210  if (compact) {
211  coutE(InputArguments) << "RooMappedCategory::readFromSteam(" << GetName() << "): can't read in compact mode" << std::endl ;
212  return kTRUE ;
213  } else {
214 
215  //Clear existing definitions, but preserve default output
216  TString defCatName(_defCat->GetName()) ;
217  _mapArray.clear() ;
218  delete _mapcache;
219  _mapcache = 0;
220  clearTypes() ;
221  _defCat = (RooCatType*) defineType(defCatName) ;
222 
223  TString token,errorPrefix("RooMappedCategory::readFromStream(") ;
224  errorPrefix.Append(GetName()) ;
225  errorPrefix.Append(")") ;
226  RooStreamParser parser(is,errorPrefix) ;
227  parser.setPunctuation(":,") ;
228 
229  TString destKey,srcKey ;
230  Bool_t readToken(kTRUE) ;
231 
232  // Loop over definition sequences
233  while(1) {
234  if (readToken) token=parser.readToken() ;
235  if (token.IsNull()) break ;
236  readToken=kTRUE ;
237 
238  destKey = token ;
239  if (parser.expectToken(":",kTRUE)) return kTRUE ;
240 
241  // Loop over list of sources for this destination
242  while(1) {
243  srcKey = parser.readToken() ;
244  token = parser.readToken() ;
245 
246  // Map a value
247  if (map(srcKey,destKey)) return kTRUE ;
248 
249  // Unless next token is ',' current token
250  // is destination part of next sequence
251  if (token.CompareTo(",")) {
252  readToken = kFALSE ;
253  break ;
254  }
255  }
256  }
257  return kFALSE ;
258  }
259  //return kFALSE ; // statement unreachable (OSF)
260 }
261 
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 /// Customized printing of arguments of a RooMappedCategory to more intuitively reflect the contents of the
265 /// product operator construction
266 
267 void RooMappedCategory::printMetaArgs(std::ostream& os) const
268 {
269  // Scan array of regexps
270  RooCatType prevOutCat ;
271  Bool_t first(kTRUE) ;
272  os << "map=(" ;
273  for (std::map<std::string,Entry>::const_iterator iter = _mapArray.begin() ; iter!=_mapArray.end() ; iter++) {
274  if (iter->second.outCat().getVal()!=prevOutCat.getVal()) {
275  if (!first) { os << " " ; }
276  first=kFALSE ;
277 
278  os << iter->second.outCat().GetName() << ":" << iter->first ;
279  prevOutCat=iter->second.outCat() ;
280  } else {
281  os << "," << iter->first ;
282  }
283  }
284 
285  if (!first) { os << " " ; }
286  os << _defCat->GetName() << ":*" ;
287 
288  os << ") " ;
289 }
290 
291 
292 
293 
294 void RooMappedCategory::writeToStream(std::ostream& os, Bool_t compact) const
295 {
296  // Write object contents to given stream
297  if (compact) {
298  // Write value only
299  os << getLabel() ;
300  } else {
301  // Write mapping expression
302 
303  // Scan array of regexps
304  RooCatType prevOutCat ;
305  Bool_t first(kTRUE) ;
306  for (std::map<std::string,Entry>::const_iterator iter = _mapArray.begin() ; iter!=_mapArray.end() ; iter++) {
307  if (iter->second.outCat().getVal()!=prevOutCat.getVal()) {
308  if (!first) { os << " " ; }
309  first=kFALSE ;
310 
311  os << iter->second.outCat().GetName() << "<-" << iter->first ;
312  prevOutCat=iter->second.outCat() ;
313  } else {
314  os << "," << iter->first ;
315  }
316  }
317 
318  if (!first) { os << " " ; }
319  os << _defCat->GetName() << ":*" ;
320  }
321 }
322 
323 
324 
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 
329 {
330  if (&other==this) return *this ;
331 
332  _expr = other._expr ;
333  _cat = other._cat ;
334 
335  if (_regexp) {
336  delete _regexp ;
337  }
338  _regexp = new TRegexp(_expr.Data(),kTRUE) ;
339 
340  return *this;
341 }
342 
343 
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Mangle name : escape regexp character '+'
347 
349 {
350  TString t ;
351  const char *c = exp ;
352  while(*c) {
353  if (*c=='+') t.Append('\\') ;
354  t.Append(*c) ;
355  c++ ;
356  }
357  return t ;
358 }
359 
360 
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 
364 void RooMappedCategory::Entry::Streamer(TBuffer &R__b)
365 {
366  typedef ::RooMappedCategory::Entry ThisClass;
367 
368  // Stream an object of class RooWorkspace::CodeRepo.
369  if (R__b.IsReading()) {
370 
371  UInt_t R__s, R__c;
372  R__b.ReadVersion(&R__s, &R__c);
373 
374  // Stream contents of ClassFiles map
375  R__b >> _expr ;
376  _cat.Streamer(R__b) ;
377  _regexp = new TRegexp(_expr.Data(),kTRUE) ;
378  R__b.CheckByteCount(R__s, R__c, ThisClass::IsA());
379 
380  } else {
381 
382  UInt_t R__c;
383  R__c = R__b.WriteVersion(ThisClass::IsA(), kTRUE);
384 
385  // Stream contents of ClassRelInfo map
386  R__b << _expr ;
387  _cat.Streamer(R__b) ;
388 
389  R__b.SetByteCount(R__c, kTRUE);
390 
391  }
392 }
#define coutE(a)
Definition: RooMsgService.h:35
Bool_t IsReading() const
Definition: TBuffer.h:81
RooMappedCategoryCache(const RooAbsCache &other, RooAbsArg *owner=0)
RooMappedCategoryCache * _mapcache
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer, which is interpreted as an OR of 'enum ContentsOptions' values and in the style given by 'enum StyleOption'.
const RooMappedCategoryCache * getOrCreateCache() const
RooCatType * _defCat
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Regular expression class.
Definition: TRegexp.h:35
void clearTypes()
Delete all currently defined states.
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
virtual void writeToStream(std::ostream &os, Bool_t compact) const
Write object contents to ostream.
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
Entry & operator=(const Entry &other)
TString mangle(const char *exp) const
Mangle name : escape regexp character '+'.
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
friend class RooMappedCategoryCache
virtual void wireCache()
virtual RooCatType evaluate() const
transient member: cache the mapping
void initialise()
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
TString & Append(const char *cs)
Definition: TString.h:492
virtual void printMultiline(std::ostream &os, Int_t contents, Bool_t verbose=kFALSE, TString indent="") const
Print info about this object to the specified stream.
const RooCatType * defineType(const char *label)
Define a new state with given name.
void printMultiline(std::ostream &os, Int_t content, Bool_t verbose=kFALSE, TString indent="") const
Print info about this object to the specified stream.
Bool_t map(const char *inKeyRegExp, const char *outKeyName, Int_t outKeyNum=NoCatIdx)
ClassImp(RooMappedCategory) ClassImp(RooMappedCategory
TString readToken()
Read one token separated by any of the know punctuation characters This function recognizes and handl...
TClass * IsA() const
unsigned int UInt_t
Definition: RtypesCore.h:42
bool verbose
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
std::map< Int_t, const RooCatType * > _map
Bool_t IsNull() const
Definition: TString.h:387
static void indent(ostringstream &buf, int indent_level)
Bool_t expectToken(const TString &expected, Bool_t zapOnError=kFALSE)
Read the next token and return kTRUE if it is identical to the given 'expected' token.
virtual Bool_t redirectServersHook(const RooAbsCollection &, Bool_t, Bool_t, Bool_t)
const RooCatType * lookup(Int_t idx) const
std::map< std::string, RooMappedCategory::Entry > _mapArray
void printMetaArgs(std::ostream &os) const
Customized printing of arguments of a RooMappedCategory to more intuitively reflect the contents of t...
virtual Bool_t readFromStream(std::istream &is, Bool_t compact, Bool_t verbose=kFALSE)
Read object contents from stream (dummy for now)
void setPunctuation(const TString &punct)
Change list of characters interpreted as punctuation.
Int_t getVal() const
Definition: RooCatType.h:80
#define name(a, b)
Definition: linkTestLib0.cpp:5
RooCategoryProxy _inputCat
virtual const char * getLabel() const
Return label string of current state.
const RooAbsCategory & arg() const
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
double exp(double)
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual const Text_t * GetName() const
Returns name of object.
Definition: RooCatType.h:45
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:385
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
const RooCatType * lookupType(Int_t index, Bool_t printError=kFALSE) const
Find our type corresponding to the specified index, or return 0 for no match.