Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooArgSet.cxx
Go to the documentation of this file.
1/***************************************************************************** * Project: RooFit *
2 * Package: RooFitCore *
3 * @(#)root/roofitcore:$Id$
4 * Authors: *
5 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
6 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
7 * *
8 * Copyright (c) 2000-2005, Regents of the University of California *
9 * and Stanford University. All rights reserved. *
10 * *
11 * Redistribution and use in source and binary forms, *
12 * with or without modification, are permitted according to the terms *
13 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
14 *****************************************************************************/
15
16//////////////////////////////////////////////////////////////////////////////
17/// \class RooArgSet
18/// RooArgSet is a container object that can hold multiple RooAbsArg objects.
19/// The container has set semantics which means that:
20///
21/// - Every object it contains must have a unique name returned by GetName().
22///
23/// - Contained objects are not ordered, although the set can be traversed
24/// just like standard library containers such as `std::vector`
25/// (in fact, the RooArgSet uses a `std::vector<RooAbsArg *>` under the hood).
26/// The iterator does not necessarily follow the object insertion order.
27///
28/// - Objects can be retrieved by name only, and not by index.
29///
30///
31/// Ownership of contents
32/// -------------------------
33/// Unowned objects are inserted with the add() method. Owned objects
34/// are added with addOwned() or addClone(). A RooArgSet either owns all
35/// of it contents, or none, which is determined by the first `add`
36/// call. Once an ownership status is selected, inappropriate `add` calls
37/// will return error status. Clearing the list via removeAll() resets the
38/// ownership status. Arguments supplied in the constructor are always added
39/// as unowned elements.
40///
41///
42/// Uniquely identifying RooArgSet objects
43/// ---------------------------------------
44///
45/// \warning Before v6.28, it was ensured that no RooArgSet objects on the heap
46/// were located at an address that had already been used for a RooArgSet before.
47/// With v6.28, this is not guaranteed anymore. Hence, if your code uses pointer
48/// comparisons to uniquely identify RooArgSet instances, please consider using
49/// the new `RooArgSet::uniqueId()`.
50
51#include "RooArgSet.h"
52
53#include "RooStreamParser.h"
54#include "RooFormulaUtils.h"
55#include "RooAbsRealLValue.h"
57#include "RooStringVar.h"
58#include "RooArgList.h"
59#include "RooSentinel.h"
60#include "RooMsgService.h"
61#include "RooConstVar.h"
62#include "strlcpy.h"
63
64#include <iostream>
65#include <fstream>
66#include <iomanip>
67#include <stdexcept>
68
69using std::istream, std::ostream, std::ifstream, std::ofstream, std::endl;
70
71
73
74
75////////////////////////////////////////////////////////////////////////////////
76/// Default constructor
77
81
82
83////////////////////////////////////////////////////////////////////////////////
84/// Constructor from a RooArgList. If the list contains multiple
85/// objects with the same name, only the first is store in the set.
86/// Warning messages will be printed for dropped items.
88 RooAbsCollection(coll.GetName())
89{
90 add(coll,true) ; // verbose to catch duplicate errors
91}
92
93
94////////////////////////////////////////////////////////////////////////////////
95/// Constructor from a RooArgSet / RooArgList and a pointer to another RooFit object.
96///
97/// \param[in] collection Collection of RooFit objects to be added. If a list contains multiple
98/// objects with the same name, only the first is stored in the set.
99/// Warning messages will be printed for dropped items.
100/// \param[in] var1 Further object to be added. If it is already in `collection`,
101/// nothing happens, and the warning message is suppressed.
102RooArgSet::RooArgSet(const RooAbsCollection& collection, const RooAbsArg* var1) :
103 RooAbsCollection(collection.GetName())
104{
105 if (var1 && !collection.contains(*var1)) {
106 add(*var1,true) ;
107 }
108 add(collection,true) ; // verbose to catch duplicate errors
109}
110
111
112////////////////////////////////////////////////////////////////////////////////
113/// Empty set constructor.
116{
117}
118
119
120////////////////////////////////////////////////////////////////////////////////
121/// Construct a set from two existing sets. The new set will not own its
122/// contents.
123RooArgSet::RooArgSet(const RooArgSet& set1, const RooArgSet& set2, const char *name) : RooAbsCollection(name)
124{
125 add(set1) ;
126 add(set2) ;
127}
128
129
130////////////////////////////////////////////////////////////////////////////////
131/// Constructor from a root TCollection. Elements in the collection that
132/// do not inherit from RooAbsArg will be skipped. A warning message
133/// will be printed for every skipped item.
134
135RooArgSet::RooArgSet(const TCollection& tcoll, const char* name) :
137{
138 for(TObject* obj : tcoll) {
139 if (!dynamic_cast<RooAbsArg*>(obj)) {
140 coutW(InputArguments) << "RooArgSet::RooArgSet(TCollection) element " << obj->GetName()
141 << " is not a RooAbsArg, ignored" << std::endl ;
142 continue ;
143 }
144 add(*static_cast<RooAbsArg*>(obj)) ;
145 }
146}
147
148
149////////////////////////////////////////////////////////////////////////////////
150/// Copy constructor. Note that a copy of a set is always non-owning,
151/// even if the source set owns its contents. To create an owning copy of
152/// a set (owning or not), use the snapshot() method.
153RooArgSet::RooArgSet(const RooArgSet& other, const char *name)
154 : RooAbsCollection(other,name)
155{
156}
157
158
159////////////////////////////////////////////////////////////////////////////////
160/// Destructor
161
165
166
167////////////////////////////////////////////////////////////////////////////////
168
169////////////////////////////////////////////////////////////////////////////////
170/// Get reference to an element using its name. Named element must exist in set.
171/// \throws invalid_argument if an element with the given name is not in the set.
172///
173/// Note that since most RooFit objects use an assignment operator that copies
174/// values, an expression like
175/// ```
176/// mySet["x"] = y;
177/// ```
178/// will not replace the element "x", it just assigns the values of y.
180{
181 RooAbsArg* arg = find(name) ;
182 if (!arg) {
183 coutE(InputArguments) << "RooArgSet::operator[](" << GetName() << ") ERROR: no element named " << name << " in set" << std::endl ;
184 throw std::invalid_argument((TString("No element named '") + name + "' in set " + GetName()).Data());
185 }
186 return *arg ;
187}
188
189
190
191////////////////////////////////////////////////////////////////////////////////
192/// Check if element with var's name is already in set
193
194bool RooArgSet::checkForDup(const RooAbsArg& var, bool silent) const
195{
196 RooAbsArg *other = find(var);
197 if (other) {
198 if (other != &var) {
199 if (!silent) {
200 // print a warning if this variable is not the same one we
201 // already have
202 coutE(InputArguments) << "RooArgSet::checkForDup: ERROR argument with name " << var.GetName() << " is already in this set" << std::endl;
203 }
204 }
205 // don't add duplicates
206 return true;
207 }
208 return false ;
209}
210
211
212
213
214
215
216
217////////////////////////////////////////////////////////////////////////////////
218/// Write contents of the argset to specified file.
219/// See writeToStream() for details
220
221void RooArgSet::writeToFile(const char* fileName) const
222{
223 ofstream ofs(fileName) ;
224 if (ofs.fail()) {
225 coutE(InputArguments) << "RooArgSet::writeToFile(" << GetName() << ") error opening file " << fileName << std::endl ;
226 return ;
227 }
228 writeToStream(ofs,false) ;
229}
230
231
232
233////////////////////////////////////////////////////////////////////////////////
234/// Read contents of the argset from specified file.
235/// See readFromStream() for details
236
237bool RooArgSet::readFromFile(const char* fileName, const char* flagReadAtt, const char* section, bool verbose)
238{
239 ifstream ifs(fileName) ;
240 if (ifs.fail()) {
241 coutE(InputArguments) << "RooArgSet::readFromFile(" << GetName() << ") error opening file " << fileName << std::endl ;
242 return true ;
243 }
244 return readFromStream(ifs,false,flagReadAtt,section,verbose) ;
245}
246
247
248
249
250////////////////////////////////////////////////////////////////////////////////
251/// Write the contents of the argset in ASCII form to given stream.
252///
253/// A line is written for each element contained in the form
254/// `<argName> = <argValue>`
255///
256/// The `<argValue>` part of each element is written by the arguments'
257/// writeToStream() function.
258/// \param os The stream to write to.
259/// \param compact Write only the bare values, separated by ' '.
260/// \note In compact mode, the stream cannot be read back into a RooArgSet,
261/// but only into a RooArgList, because the variable names are lost.
262/// \param section If non-null, add a section header like `[<section>]`.
263void RooArgSet::writeToStream(ostream& os, bool compact, const char* section) const
264{
265 if (section && section[0] != '\0')
266 os << '[' << section << ']' << '\n';
267
268 if (compact) {
269 for (const auto next : _list) {
270 next->writeToStream(os, true);
271 os << " ";
272 }
273 os << std::endl;
274 } else {
275 for (const auto next : _list) {
276 os << next->GetName() << " = " ;
277 next->writeToStream(os,false) ;
278 os << std::endl ;
279 }
280 }
281}
282
283
284
285
286////////////////////////////////////////////////////////////////////////////////
287/// Read the contents of the argset in ASCII form from given stream.
288///
289/// The stream is read to end-of-file and each line is assumed to be
290/// of the form
291/// \code
292/// <argName> = <argValue>
293/// \endcode
294/// Lines starting with argNames not matching any element in the list
295/// will be ignored with a warning message. In addition limited C++ style
296/// preprocessing and flow control is provided. The following constructions
297/// are recognized:
298/// \code
299/// include "include.file"
300/// \endcode
301/// Include given file, recursive inclusion OK
302/// \code
303/// if (<boolean_expression>)
304/// <name> = <value>
305/// ....
306/// else if (<boolean_expression>)
307/// ....
308/// else
309/// ....
310/// endif
311/// \endcode
312///
313/// All expressions are evaluated by RooFormula, and may involve any of
314/// the sets variables.
315/// \code
316/// echo <Message>
317/// \endcode
318/// Print console message while reading from stream
319/// \code
320/// abort
321/// \endcode
322/// Force termination of read sequence with error status
323///
324/// The value of each argument is read by the arguments readFromStream
325/// function.
326
327bool RooArgSet::readFromStream(istream& is, bool compact, const char* flagReadAtt, const char* section, bool verbose)
328{
329 if (compact) {
330 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << ") compact mode not supported" << std::endl ;
331 return true ;
332 }
333
334 RooStreamParser parser(is) ;
335 parser.setPunctuation("=") ;
336 TString token ;
337 bool retVal(false) ;
338
339 // Conditional stack and related state variables
340 // coverity[UNINIT]
341 bool anyCondTrue[100] ;
342 bool condStack[100] ;
343 bool lastLineWasElse=false ;
344 Int_t condStackLevel=0 ;
345 condStack[0]=true ;
346
347 // Prepare section processing
348 TString sectionHdr("[") ;
349 if (section) sectionHdr.Append(section) ;
350 sectionHdr.Append("]") ;
351 bool inSection(section?false:true) ;
352
353 bool reprocessToken = false ;
354 while (true) {
355
356 if (is.eof() || is.fail() || parser.atEOF()) {
357 break ;
358 }
359
360 // Read next token until memEnd of file
361 if (!reprocessToken) {
362 token = parser.readToken() ;
363 }
364 reprocessToken = false ;
365
366 // Skip empty lines
367 if (token.IsNull()) {
368 continue ;
369 }
370
371 // Process include directives
372 if (!token.CompareTo("include")) {
373 if (parser.atEOL()) {
374 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName()
375 << "): no filename found after include statement" << std::endl ;
376 return true ;
377 }
378 TString filename = parser.readLine() ;
379 ifstream incfs(filename) ;
380 if (!incfs.good()) {
381 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): cannot open include file " << filename << std::endl ;
382 return true ;
383 }
384 coutI(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): processing include file "
385 << filename << std::endl ;
386 if (readFromStream(incfs,compact,flagReadAtt,inSection?nullptr:section,verbose)) return true ;
387 continue ;
388 }
389
390 // Process section headers if requested
391 if (*token.Data()=='[') {
392 TString hdr(token) ;
393 const char* last = token.Data() + token.Length() -1 ;
394 if (*last != ']') {
395 hdr.Append(" ") ;
396 hdr.Append(parser.readLine()) ;
397 }
398 // parser.putBackToken(token) ;
399 // token = parser.readLine() ;
400 if (section) {
401 inSection = !sectionHdr.CompareTo(hdr) ;
402 }
403 continue ;
404 }
405
406 // If section is specified, ignore all data outside specified section
407 if (!inSection) {
408 parser.zapToEnd(true) ;
409 continue ;
410 }
411
412 // Conditional statement evaluation
413 if (!token.CompareTo("if")) {
414
415 // Extract conditional expressions and check validity
416 TString expr = parser.readLine() ;
417 auto form = RooFormulaUtils::makeFormulaEvaluator(expr.Data(), expr.Data(), *this);
418
419 // Evaluate expression
420 bool status = RooFormulaUtils::evalFormula(*form, *this) ? true : false;
421 if (lastLineWasElse) {
422 anyCondTrue[condStackLevel] |= status ;
423 lastLineWasElse=false ;
424 } else {
425 condStackLevel++ ;
426 anyCondTrue[condStackLevel] = status ;
427 }
428 condStack[condStackLevel] = status ;
429
430 if (verbose) {
431 cxcoutD(Eval) << "RooArgSet::readFromStream(" << GetName() << "): conditional expression " << expr << " = "
432 << (condStack[condStackLevel] ? "true" : "false") << std::endl;
433 }
434 continue ; // go to next line
435 }
436
437 if (!token.CompareTo("else")) {
438 // Must have seen an if statement before
439 if (condStackLevel==0) {
440 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'else'" << std::endl ;
441 }
442
443 if (parser.atEOL()) {
444 // simple else: process if nothing else was true
445 condStack[condStackLevel] = !anyCondTrue[condStackLevel] ;
446 parser.zapToEnd(false) ;
447 continue ;
448 } else {
449 // if anything follows it should be 'if'
450 token = parser.readToken() ;
451 if (token.CompareTo("if")) {
452 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): syntax error: 'else " << token << "'" << std::endl ;
453 return true ;
454 } else {
455 if (anyCondTrue[condStackLevel]) {
456 // No need for further checking, true conditional already processed
457 condStack[condStackLevel] = false ;
458 parser.zapToEnd(false) ;
459 continue ;
460 } else {
461 // Process as normal 'if' no true conditional was encountered
462 reprocessToken = true ;
463 lastLineWasElse=true ;
464 continue ;
465 }
466 }
467 }
468 }
469
470 if (!token.CompareTo("endif")) {
471 // Must have seen an if statement before
472 if (condStackLevel==0) {
473 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'endif'" << std::endl ;
474 return true ;
475 }
476
477 // Decrease stack by one
478 condStackLevel-- ;
479 continue ;
480 }
481
482 // If current conditional is true
483 if (condStack[condStackLevel]) {
484
485 // Process echo statements
486 if (!token.CompareTo("echo")) {
487 TString message = parser.readLine() ;
488 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): >> " << message << std::endl ;
489 continue ;
490 }
491
492 // Process abort statements
493 if (!token.CompareTo("abort")) {
494 TString message = parser.readLine() ;
495 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): USER ABORT" << std::endl ;
496 return true ;
497 }
498
499 // Interpret the rest as <arg> = <value_expr>
500 RooAbsArg *arg ;
501
502 if ((arg = find(token)) && !arg->getAttribute("Dynamic")) {
503 if (parser.expectToken("=",true)) {
504 parser.zapToEnd(true) ;
505 retVal=true ;
506 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName()
507 << "): missing '=' sign: " << arg << std::endl ;
508 continue ;
509 }
510 bool argRet = arg->readFromStream(is,false,verbose) ;
511 if (!argRet && flagReadAtt) arg->setAttribute(flagReadAtt,true) ;
512 retVal |= argRet ;
513 } else {
514 if (verbose) {
515 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): argument "
516 << token << " not in list, ignored" << std::endl ;
517 }
518 parser.zapToEnd(true) ;
519 }
520 } else {
521 parser.readLine() ;
522 }
523 }
524
525 // Did we fully unwind the conditional stack?
526 if (condStackLevel!=0) {
527 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): missing 'endif'" << std::endl ;
528 return true ;
529 }
530
531 return retVal ;
532}
533
534
535bool RooArgSet::isInRange(const char* rangeSpec)
536{
537 char buf[1024] ;
538 strlcpy(buf,rangeSpec,1024) ;
539 char* token = strtok(buf,",") ;
540
541 while(token) {
542
543 bool accept=true ;
544 for (auto * lvarg : dynamic_range_cast<RooAbsRealLValue*>(*this)) {
545 if (lvarg) {
546 if (!lvarg->inRange(token)) {
547 accept=false ;
548 break ;
549 }
550 }
551 // WVE MUST HANDLE RooAbsCategoryLValue ranges as well
552 }
553 if (accept) {
554 return true ;
555 }
556
557 token = strtok(nullptr,",") ;
558 }
559
560 return false ;
561}
562
563
#define coutI(a)
#define cxcoutD(a)
#define coutW(a)
#define coutE(a)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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
virtual bool readFromStream(std::istream &is, bool compact, bool verbose=false)=0
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
Abstract container object that can hold multiple RooAbsArg objects.
bool contains(const char *name) const
Check if collection contains an argument with a specific name.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t _list
Actual object storage.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
bool isInRange(const char *rangeSpec)
bool checkForDup(const RooAbsArg &arg, bool silent) const
Check if element with var's name is already in set.
RooArgSet()
Default constructor.
Definition RooArgSet.cxx:78
~RooArgSet() override
Destructor.
void writeToFile(const char *fileName) const
Write contents of the argset to specified file.
bool readFromFile(const char *fileName, const char *flagReadAtt=nullptr, const char *section=nullptr, bool verbose=false)
Read contents of the argset from specified file.
static void cleanup()
Definition RooArgSet.cxx:72
virtual bool readFromStream(std::istream &is, bool compact, bool verbose=false)
Shortcut for readFromStream(std::istream&, bool, const char*, const char*, bool), setting flagReadAtt...
Definition RooArgSet.h:121
void processArg(const RooAbsArg &arg)
Definition RooArgSet.h:177
RooAbsArg & operator[](const TString &str) const
Get reference to an element using its name.
virtual void writeToStream(std::ostream &os, bool compact, const char *section=nullptr) const
Write the contents of the argset in ASCII form to given stream.
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.
bool atEOL()
If true, parser is at end of line in stream.
TString readLine()
Read an entire line from the stream and return as TString This method recognizes the use of '\' in th...
TString readToken()
Read one token separated by any of the know punctuation characters This function recognizes and handl...
void zapToEnd(bool inclContLines=false)
Eat all characters up to and including then end of the current line.
Collection abstract base class.
Definition TCollection.h:65
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:42
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:465
const char * Data() const
Definition TString.h:385
Bool_t IsNull() const
Definition TString.h:423
TString & Append(const char *cs)
Definition TString.h:582
RooConstVar & RooConst(double val)