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:
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
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 {
93 }
94}
95
98 _inputCat("input", this, other._inputCat),
99 _mapArray(other._mapArray)
100{
101 setDefCat(lookupIndex(other.lookupName(other._defCat)));
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
125 if (catIdx == invalidCategory().second) {
126 if (outIdx==NoCatIdx) {
127 catIdx = defineState(outKey).second;
128 } else {
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 ;
141 if (!e.ok()) {
142 coutE(InputArguments) << "RooMappedCategory::map(" << GetName()
143 << "): ERROR, expression " << inKeyRegExp << " didn't compile" << std::endl ;
144 return true ;
145 }
146
148 return false ;
149}
150
151
152
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
176
177 if (verbose) {
178 os << indent << "--- RooMappedCategory ---" << std::endl
179 << indent << " Maps from " ;
180 _inputCat.arg().printStream(os,0,kStandard);
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
202 _mapArray.clear() ;
203 _mapcache = nullptr;
204 clearTypes() ;
205 _defCat = defineState(defCatName.Data()).second;
206
208 TString errorPrefix("RooMappedCategory::readFromStream(");
209 errorPrefix.Append(GetName()) ;
210 errorPrefix.Append(")") ;
212 parser.setPunctuation(":,") ;
213
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
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
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
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)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:142
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
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.
static const decltype(_stateNames) ::value_type & invalidCategory()
A category state to signify an invalid category.
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.
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 '+'.
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)
const T & arg() const
Return reference to object held in proxy.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Regular expression class.
Definition TRegexp.h:31
@ kOK
Definition TRegexp.h:34
Basic string class.
Definition TString.h:138
TString & Append(const char *cs)
Definition TString.h:583