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