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