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 "RooFormula.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.
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.
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
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.
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] ;
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 }
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 RooFormula form(expr,expr,*this) ;
418 if (!form.ok()) return true ;
419
420 // Evaluate expression
421 bool status = form.eval()?true:false ;
422 if (lastLineWasElse) {
423 anyCondTrue[condStackLevel] |= status ;
425 } else {
427 anyCondTrue[condStackLevel] = status ;
428 }
429 condStack[condStackLevel] = status ;
430
431 if (verbose) {
432 cxcoutD(Eval) << "RooArgSet::readFromStream(" << GetName() << "): conditional expression " << expr << " = "
433 << (condStack[condStackLevel] ? "true" : "false") << std::endl;
434 }
435 continue ; // go to next line
436 }
437
438 if (!token.CompareTo("else")) {
439 // Must have seen an if statement before
440 if (condStackLevel==0) {
441 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'else'" << std::endl ;
442 }
443
444 if (parser.atEOL()) {
445 // simple else: process if nothing else was true
447 parser.zapToEnd(false) ;
448 continue ;
449 } else {
450 // if anything follows it should be 'if'
451 token = parser.readToken() ;
452 if (token.CompareTo("if")) {
453 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): syntax error: 'else " << token << "'" << std::endl ;
454 return true ;
455 } else {
457 // No need for further checking, true conditional already processed
459 parser.zapToEnd(false) ;
460 continue ;
461 } else {
462 // Process as normal 'if' no true conditional was encountered
465 continue ;
466 }
467 }
468 }
469 }
470
471 if (!token.CompareTo("endif")) {
472 // Must have seen an if statement before
473 if (condStackLevel==0) {
474 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'endif'" << std::endl ;
475 return true ;
476 }
477
478 // Decrease stack by one
480 continue ;
481 }
482
483 // If current conditional is true
485
486 // Process echo statements
487 if (!token.CompareTo("echo")) {
488 TString message = parser.readLine() ;
489 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): >> " << message << std::endl ;
490 continue ;
491 }
492
493 // Process abort statements
494 if (!token.CompareTo("abort")) {
495 TString message = parser.readLine() ;
496 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): USER ABORT" << std::endl ;
497 return true ;
498 }
499
500 // Interpret the rest as <arg> = <value_expr>
501 RooAbsArg *arg ;
502
503 if ((arg = find(token)) && !arg->getAttribute("Dynamic")) {
504 if (parser.expectToken("=",true)) {
505 parser.zapToEnd(true) ;
506 retVal=true ;
507 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName()
508 << "): missing '=' sign: " << arg << std::endl ;
509 continue ;
510 }
511 bool argRet = arg->readFromStream(is,false,verbose) ;
512 if (!argRet && flagReadAtt) arg->setAttribute(flagReadAtt,true) ;
513 retVal |= argRet ;
514 } else {
515 if (verbose) {
516 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): argument "
517 << token << " not in list, ignored" << std::endl ;
518 }
519 parser.zapToEnd(true) ;
520 }
521 } else {
522 parser.readLine() ;
523 }
524 }
525
526 // Did we fully unwind the conditional stack?
527 if (condStackLevel!=0) {
528 coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): missing 'endif'" << std::endl ;
529 return true ;
530 }
531
532 return retVal ;
533}
534
535
537{
538 char buf[1024] ;
539 strlcpy(buf,rangeSpec,1024) ;
540 char* token = strtok(buf,",") ;
541
542 while(token) {
543
544 bool accept=true ;
545 for (auto * lvarg : dynamic_range_cast<RooAbsRealLValue*>(*this)) {
546 if (lvarg) {
547 if (!lvarg->inRange(token)) {
548 accept=false ;
549 break ;
550 }
551 }
552 // WVE MUST HANDLE RooAbsCategoryLValue ranges as well
553 }
554 if (accept) {
555 return true ;
556 }
557
558 token = strtok(nullptr,",") ;
559 }
560
561 return false ;
562}
563
564
#define coutI(a)
#define cxcoutD(a)
#define coutW(a)
#define coutE(a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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:148
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.
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:138
RooConstVar & RooConst(double val)