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.
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
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 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 ;
424 } else {
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
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 {
456 // No need for further checking, true conditional already processed
458 parser.zapToEnd(false) ;
459 continue ;
460 } else {
461 // Process as normal 'if' no true conditional was encountered
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
479 continue ;
480 }
481
482 // If current conditional is true
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
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)
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: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.
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.
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)