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