Logo ROOT  
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 RooMappedCategory
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 "RooMappedCategory.h"
26
27#include "RooFit.h"
28#include "RooStreamParser.h"
29#include "RooMsgService.h"
30#include "Riostream.h"
31#include "RooAbsCache.h"
32
33#include "TBuffer.h"
34#include "TString.h"
35#include "TRegexp.h"
36
37
38class RooMappedCategoryCache : public RooAbsCache {
39 public:
40 RooMappedCategoryCache(RooAbsArg* owner = 0) : RooAbsCache(owner)
41 { initialise(); }
42 RooMappedCategoryCache(const RooAbsCache& other, RooAbsArg* owner = 0) :
43 RooAbsCache(other, owner)
44 { initialise(); }
45
46 // look up our parent's output based on our parent's input category index
47 RooAbsCategory::value_type lookup(Int_t idx) const
48 { return _map[idx]; }
49
50 virtual void wireCache()
51 { _map.clear(); initialise(); }
52
53 virtual Bool_t redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, Bool_t /*nameChange*/, Bool_t /*isRecursive*/)
54 { _map.clear(); initialise(); return kFALSE; }
55
56 private:
57 mutable std::map<Int_t, RooAbsCategory::value_type> _map;
58
59 // pre-map categories of input category on something easily searchable
60 // like the index (not the name!)
61 void initialise()
62 {
63 const RooMappedCategory& parent = *static_cast<const RooMappedCategory*>(_owner);
64
65 for (const auto& inCat : *parent._inputCat) {
66 const std::string& inKey = inCat.first;
67 // Scan array of regexps
68 bool found = false;
69 for (const auto& strAndEntry : parent._mapArray) {
70 if (strAndEntry.second.match(inKey.c_str())) {
71 found = true;
72 _map[inCat.second] = strAndEntry.second.outCat();
73 break;
74 }
75 }
76
77 if (!found)
78 _map[inCat.second] = parent._defCat;
79 }
80 }
81};
82
83RooMappedCategory::RooMappedCategory(const char *name, const char *title, RooAbsCategory& inputCat, const char* defOut, Int_t defOutIdx) :
84 RooAbsCategory(name, title), _inputCat("input","Input category",this,inputCat),
85 _mapcache(0)
86{
87 // Constructor with input category and name of default output state, which is assigned
88 // to all input category states that do not follow any mapping rule.
89 if (defOutIdx==NoCatIdx) {
90 _defCat = defineState(defOut).second;
91 } else {
92 _defCat = defineState(defOut,defOutIdx).second;
93 }
94}
95
96
98 RooAbsCategory(other,name), _inputCat("input",this,other._inputCat), _mapArray(other._mapArray),
99 _mapcache(0)
100{
101 _defCat = lookupIndex(other.lookupName(other._defCat));
102}
103
104
105
107{
108 // Destructor
109 delete _mapcache;
110}
111
112
113
114Bool_t RooMappedCategory::map(const char* inKeyRegExp, const char* outKey, Int_t outIdx)
115{
116 // Add mapping rule: any input category state label matching the 'inKeyRegExp'
117 // wildcard expression will be mapped to an output state with name 'outKey'
118 //
119 // Rules are evaluated in the order they were added. In case an input state
120 // matches more than one rule, the first rules output state will be assigned
121
122 if (!inKeyRegExp || !outKey) return kTRUE ;
123
124 // Check if pattern is already registered
125 if (_mapArray.find(inKeyRegExp)!=_mapArray.end()) {
126 coutE(InputArguments) << "RooMappedCategory::map(" << GetName() << "): ERROR expression "
127 << inKeyRegExp << " already mapped" << std::endl ;
128 return kTRUE ;
129 }
130
131 // Check if output type exists, if not register
132 value_type catIdx = lookupIndex(outKey);
133 if (catIdx == invalidCategory().second) {
134 if (outIdx==NoCatIdx) {
135 catIdx = defineState(outKey).second;
136 } else {
137 catIdx = defineState(outKey,outIdx).second;
138 }
139 }
140
141 if (catIdx == invalidCategory().second) {
142 coutE(InputArguments) << "RooMappedCategory::map(" << GetName()
143 << "): ERROR, unable to define category for output type " << outKey << std::endl ;
144 return true;
145 }
146
147 // Create new map entry ;
148 Entry e(inKeyRegExp, catIdx);
149 if (!e.ok()) {
150 coutE(InputArguments) << "RooMappedCategory::map(" << GetName()
151 << "): ERROR, expression " << inKeyRegExp << " didn't compile" << std::endl ;
152 return kTRUE ;
153 }
154
155 _mapArray[inKeyRegExp] = e ;
156 return kFALSE ;
157}
158
159
160
162{
164 return cache->lookup(_inputCat->getCurrentIndex());
165}
166
167const RooMappedCategoryCache* RooMappedCategory::getOrCreateCache() const
168{
170 const_cast<RooMappedCategory*>(this));
171 return _mapcache;
172}
173
175{
176 // Print info about this mapped category to the specified stream. In addition to the info
177 // from RooAbsCategory::printStream() we add:
178 //
179 // Standard : input category
180 // Shape : default value
181 // Verbose : list of mapping rules
182
184
185 if (verbose) {
186 os << indent << "--- RooMappedCategory ---" << std::endl
187 << indent << " Maps from " ;
189
190 os << indent << " Default value is " << lookupName(_defCat) << " = " << _defCat << '\n';
191
192 os << indent << " Mapping rules:" << std::endl;
193 for (const auto& strAndEntry : _mapArray) {
194 os << indent << " " << strAndEntry.first << " -> " << strAndEntry.second.outCat() << std::endl ;
195 }
196 }
197}
198
199
200Bool_t RooMappedCategory::readFromStream(std::istream& is, Bool_t compact, Bool_t /*verbose*/)
201{
202 // Read object contents from given stream
203 if (compact) {
204 coutE(InputArguments) << "RooMappedCategory::readFromSteam(" << GetName() << "): can't read in compact mode" << std::endl ;
205 return kTRUE ;
206 } else {
207
208 //Clear existing definitions, but preserve default output
209 TString defCatName(lookupName(_defCat));
210 _mapArray.clear() ;
211 delete _mapcache;
212 _mapcache = 0;
213 clearTypes() ;
214 _defCat = defineState(defCatName.Data()).second;
215
216 TString token,errorPrefix("RooMappedCategory::readFromStream(") ;
217 errorPrefix.Append(GetName()) ;
218 errorPrefix.Append(")") ;
219 RooStreamParser parser(is,errorPrefix) ;
220 parser.setPunctuation(":,") ;
221
222 TString destKey,srcKey ;
223 Bool_t readToken(kTRUE) ;
224
225 // Loop over definition sequences
226 while(1) {
227 if (readToken) token=parser.readToken() ;
228 if (token.IsNull()) break ;
229 readToken=kTRUE ;
230
231 destKey = token ;
232 if (parser.expectToken(":",kTRUE)) return kTRUE ;
233
234 // Loop over list of sources for this destination
235 while(1) {
236 srcKey = parser.readToken() ;
237 token = parser.readToken() ;
238
239 // Map a value
240 if (map(srcKey,destKey)) return kTRUE ;
241
242 // Unless next token is ',' current token
243 // is destination part of next sequence
244 if (token.CompareTo(",")) {
245 readToken = kFALSE ;
246 break ;
247 }
248 }
249 }
250 return kFALSE ;
251 }
252 //return kFALSE ; // statement unreachable (OSF)
253}
254
255
256////////////////////////////////////////////////////////////////////////////////
257/// Customized printing of arguments of a RooMappedCategory to more intuitively reflect the contents of the
258/// product operator construction
259
260void RooMappedCategory::printMetaArgs(std::ostream& os) const
261{
262 // Scan array of regexps
263 RooAbsCategory::value_type prevOutCat = invalidCategory().second;
265 os << "map=(" ;
266 for (const auto& iter : _mapArray) {
267 if (iter.second.outCat() != prevOutCat) {
268 if (!first) { os << " " ; }
269 first=kFALSE ;
270
271 os << iter.second.outCat() << ":" << iter.first ;
272 prevOutCat = iter.second.outCat();
273 } else {
274 os << "," << iter.first ;
275 }
276 }
277
278 if (!first) { os << " " ; }
279 os << lookupName(_defCat) << ":*" ;
280
281 os << ") " ;
282}
283
284
285
286
287void RooMappedCategory::writeToStream(std::ostream& os, Bool_t compact) const
288{
289 // Write object contents to given stream
290 if (compact) {
291 // Write value only
292 os << getCurrentLabel() ;
293 } else {
294 // Write mapping expression
295
296 // Scan array of regexps
297 RooAbsCategory::value_type prevOutCat = invalidCategory().second;
299 for (const auto& iter : _mapArray) {
300 if (iter.second.outCat() != prevOutCat) {
301 if (!first) { os << " " ; }
302 first=kFALSE ;
303
304 os << iter.second.outCat() << "<-" << iter.first ;
305 prevOutCat = iter.second.outCat();
306 } else {
307 os << "," << iter.first ;
308 }
309 }
310
311 if (!first) { os << " " ; }
312 os << lookupName(_defCat) << ":*" ;
313 }
314}
315
316
317/// When the input category changes states, the cached state mappings are invalidated
319 // There is no need to recompute _stateNames and _insertionOrder, as only defining new
320 // mappings has an effect on these. When the input category changes it shape, it is sufficient
321 // to clear the cached state mappings.
322 if (_mapcache) {
323 _mapcache->wireCache();
324 }
325}
326
327
329 _expr(exp), _regexp(nullptr), _catIdx(cat) {}
331 _expr(other._expr), _regexp(nullptr), _catIdx(other._catIdx) {}
333bool RooMappedCategory::Entry::ok() { return (const_cast<TRegexp*>(regexp())->Status()==TRegexp::kOK) ; }
334
335////////////////////////////////////////////////////////////////////////////////
336
338{
339 if (&other==this) return *this ;
340
341 _expr = other._expr ;
342 _catIdx = other._catIdx;
343
344 if (_regexp) {
345 delete _regexp ;
346 }
347
348 return *this;
349}
350
351bool RooMappedCategory::Entry::match(const char* testPattern) const {
352 return (TString(testPattern).Index(*regexp())>=0);
353}
354
355////////////////////////////////////////////////////////////////////////////////
356/// Mangle name : escape regexp character '+'
357
359{
360 TString t ;
361 const char *c = exp ;
362 while(*c) {
363 if (*c=='+') t.Append('\\') ;
364 t.Append(*c) ;
365 c++ ;
366 }
367 return t ;
368}
369
371 if (!_regexp) {
372 _regexp = new TRegexp(mangle(_expr), true);
373 }
374
375 return _regexp;
376}
#define c(i)
Definition: RSha256.hxx:101
#define e(i)
Definition: RSha256.hxx:103
static void initialise(gsl_integration_workspace *workspace, double a, double b)
#define coutE(a)
Definition: RooMsgService.h:33
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
const Bool_t kTRUE
Definition: RtypesCore.h:89
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition: TGX11.cxx:109
double exp(double)
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:73
RooAbsCache is the abstract base class for data members of RooAbsArgs that cache other (composite) Ro...
Definition: RooAbsCache.h:27
virtual Bool_t redirectServersHook(const RooAbsCollection &, Bool_t, Bool_t, Bool_t)
Interface for server redirect calls.
Definition: RooAbsCache.cxx:89
RooAbsArg * _owner
Definition: RooAbsCache.h:44
virtual void wireCache()
Definition: RooAbsCache.h:38
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual value_type getCurrentIndex() const
Return index number of current state.
virtual const char * getCurrentLabel() const
Return label string of current state.
const std::string & lookupName(value_type index) const
Get the name corresponding to the given index.
virtual const std::map< std::string, RooAbsCategory::value_type >::value_type & defineState(const std::string &label)
Define a new state with given label.
int value_type
The type used to denote a specific category state.
static const decltype(_stateNames) ::value_type & invalidCategory()
Is this category attached to a tree?
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.
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
void clearTypes()
Delete all currently defined states.
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
Entry & operator=(const Entry &other)
const TRegexp * regexp() const
TString mangle(const char *exp) const
Mangle name : escape regexp character '+'.
RooAbsCategory::value_type _catIdx
Bool_t match(const char *testPattern) const
RooMappedCategory provides a category-to-category mapping defined by pattern matching on their state ...
const RooMappedCategoryCache * getOrCreateCache() const
RooCategoryProxy _inputCat
virtual value_type evaluate() const
transient member: cache the mapping
virtual Bool_t readFromStream(std::istream &is, Bool_t compact, Bool_t verbose=kFALSE)
Read object contents from stream (dummy for now)
virtual void writeToStream(std::ostream &os, Bool_t compact) const
Write object contents to ostream.
std::map< std::string, RooMappedCategory::Entry > _mapArray
friend class RooMappedCategoryCache
Bool_t map(const char *inKeyRegExp, const char *outKeyName, Int_t outKeyNum=NoCatIdx)
void printMetaArgs(std::ostream &os) const
Customized printing of arguments of a RooMappedCategory to more intuitively reflect the contents of t...
static constexpr value_type NoCatIdx
RooMappedCategoryCache * _mapcache
void recomputeShape()
When the input category changes states, the cached state mappings are invalidated.
void printMultiline(std::ostream &os, Int_t content, Bool_t verbose=kFALSE, TString indent="") const
Print info about this object to the specified stream.
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,...
void setPunctuation(const TString &punct)
Change list of characters interpreted as punctuation.
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.
TString readToken()
Read one token separated by any of the know punctuation characters This function recognizes and handl...
const T & arg() const
Return reference to object held in proxy.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Regular expression class.
Definition: TRegexp.h:31
@ kOK
Definition: TRegexp.h:34
Basic string class.
Definition: TString.h:131
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:418
const char * Data() const
Definition: TString.h:364
Bool_t IsNull() const
Definition: TString.h:402
TString & Append(const char *cs)
Definition: TString.h:559
RooCmdArg Index(RooCategory &icat)
@ InputArguments
Definition: RooGlobalFunc.h:68
static constexpr double second
Definition: first.py:1