Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
42 #include "RooArgSet.h"
43 
44 #include "Riostream.h"
45 #include "TClass.h"
46 #include "RooErrorHandler.h"
47 #include "RooStreamParser.h"
48 #include "RooFormula.h"
49 #include "RooAbsRealLValue.h"
50 #include "RooAbsCategoryLValue.h"
51 #include "RooStringVar.h"
52 #include "RooTrace.h"
53 #include "RooArgList.h"
54 #include "RooSentinel.h"
55 #include "RooMsgService.h"
56 #include "ROOT/RMakeUnique.hxx"
57 
58 #include <iomanip>
59 
60 using namespace std ;
61 
62 #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
63 char* operator+( streampos&, char* );
64 #endif
65 
66 ClassImp(RooArgSet);
67 
68 
69 
70 #ifndef USEMEMPOOLFORARGSET
71 void RooArgSet::cleanup() { }
72 #else
73 
74 #include "MemPoolForRooSets.h"
75 
76 RooArgSet::MemPool* RooArgSet::memPool() {
77  RooSentinel::activate();
78  static auto * memPool = new RooArgSet::MemPool();
79  return memPool;
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Clear memory pool on exit to avoid reported memory leaks
84 
85 void RooArgSet::cleanup()
86 {
87  auto pool = memPool();
88  memPool()->teardown();
89 
90  //Here, the pool might have to leak if RooArgSets are still alive.
91  if (pool->empty())
92  delete pool;
93 }
94 
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Overloaded new operator guarantees that all RooArgSets allocated with new
98 /// have a unique address, a property that is exploited in several places
99 /// in roofit to quickly index contents on normalization set pointers.
100 /// The memory pool only allocates space for the class itself. The elements
101 /// stored in the set are stored outside the pool.
102 
103 void* RooArgSet::operator new (size_t bytes)
104 {
105  //This will fail if a derived class uses this operator
106  assert(sizeof(RooArgSet) == bytes);
107 
108  return memPool()->allocate(bytes);
109 }
110 
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Overloaded new operator with placement does not guarante that all
114 /// RooArgSets allocated with new have a unique address, but uses the global
115 /// operator.
116 
117 void* RooArgSet::operator new (size_t bytes, void* ptr) noexcept
118 {
119  return ::operator new (bytes, ptr);
120 }
121 
122 
123 ////////////////////////////////////////////////////////////////////////////////
124 /// Memory is owned by pool, we need to do nothing to release it
125 
126 void RooArgSet::operator delete (void* ptr)
127 {
128  // Decrease use count in pool that ptr is on
129  if (memPool()->deallocate(ptr))
130  return;
131 
132  std::cerr << __func__ << " " << ptr << " is not in any of the pools." << std::endl;
133 
134  // Not part of any pool; use global op delete:
135  ::operator delete(ptr);
136 }
137 
138 #endif
139 
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// Default constructor
143 
144 RooArgSet::RooArgSet() :
145  RooAbsCollection()
146 {
147  TRACE_CREATE
148 }
149 
150 
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 /// Constructor from a RooArgList. If the list contains multiple
154 /// objects with the same name, only the first is store in the set.
155 /// Warning messages will be printed for dropped items.
156 
157 RooArgSet::RooArgSet(const RooArgList& list) :
158  RooAbsCollection(list.GetName())
159 {
160  add(list,kTRUE) ; // verbose to catch duplicate errors
161  TRACE_CREATE
162 }
163 
164 
165 
166 ////////////////////////////////////////////////////////////////////////////////
167 /// Constructor from a RooArgList. If the list contains multiple
168 /// objects with the same name, only the first is store in the set.
169 /// Warning messages will be printed for dropped items.
170 
171 RooArgSet::RooArgSet(const RooArgList& list, const RooAbsArg* var1) :
172  RooAbsCollection(list.GetName())
173 {
174  if (var1 && !list.contains(*var1)) {
175  add(*var1,kTRUE) ;
176  }
177  add(list,kTRUE) ; // verbose to catch duplicate errors
178  TRACE_CREATE
179 }
180 
181 
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Empty set constructor
185 
186 RooArgSet::RooArgSet(const char *name) :
187  RooAbsCollection(name)
188 {
189  TRACE_CREATE
190 }
191 
192 
193 
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Construct a set from two existing sets
197 
198 RooArgSet::RooArgSet(const RooArgSet& set1, const RooArgSet& set2, const char *name) : RooAbsCollection(name)
199 {
200  add(set1) ;
201  add(set2) ;
202  TRACE_CREATE
203 }
204 
205 
206 
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 /// Constructor for set containing 1 initial object
210 
211 RooArgSet::RooArgSet(const RooAbsArg& var1,
212  const char *name) :
213  RooAbsCollection(name)
214 {
215  add(var1);
216  TRACE_CREATE
217 }
218 
219 
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Constructor for set containing 2 initial objects
223 
224 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
225  const char *name) :
226  RooAbsCollection(name)
227 {
228  add(var1); add(var2);
229  TRACE_CREATE
230 }
231 
232 
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Constructor for set containing 3 initial objects
236 
237 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
238  const RooAbsArg& var3,
239  const char *name) :
240  RooAbsCollection(name)
241 {
242  add(var1); add(var2); add(var3);
243  TRACE_CREATE
244 }
245 
246 
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Constructor for set containing 4 initial objects
250 
251 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
252  const RooAbsArg& var3, const RooAbsArg& var4,
253  const char *name) :
254  RooAbsCollection(name)
255 {
256  add(var1); add(var2); add(var3); add(var4);
257  TRACE_CREATE
258 }
259 
260 
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Constructor for set containing 5 initial objects
264 
265 RooArgSet::RooArgSet(const RooAbsArg& var1,
266  const RooAbsArg& var2, const RooAbsArg& var3,
267  const RooAbsArg& var4, const RooAbsArg& var5,
268  const char *name) :
269  RooAbsCollection(name)
270 {
271  add(var1); add(var2); add(var3); add(var4); add(var5);
272  TRACE_CREATE
273 }
274 
275 
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// Constructor for set containing 6 initial objects
279 
280 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
281  const RooAbsArg& var3, const RooAbsArg& var4,
282  const RooAbsArg& var5, const RooAbsArg& var6,
283  const char *name) :
284  RooAbsCollection(name)
285 {
286  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6);
287  TRACE_CREATE
288 }
289 
290 
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// Constructor for set containing 7 initial objects
294 
295 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
296  const RooAbsArg& var3, const RooAbsArg& var4,
297  const RooAbsArg& var5, const RooAbsArg& var6,
298  const RooAbsArg& var7,
299  const char *name) :
300  RooAbsCollection(name)
301 {
302  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7) ;
303  TRACE_CREATE
304 }
305 
306 
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Constructor for set containing 8 initial objects
310 
311 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
312  const RooAbsArg& var3, const RooAbsArg& var4,
313  const RooAbsArg& var5, const RooAbsArg& var6,
314  const RooAbsArg& var7, const RooAbsArg& var8,
315  const char *name) :
316  RooAbsCollection(name)
317 {
318  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7) ;add(var8) ;
319  TRACE_CREATE
320 }
321 
322 
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Constructor for set containing 9 initial objects
326 
327 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
328  const RooAbsArg& var3, const RooAbsArg& var4,
329  const RooAbsArg& var5, const RooAbsArg& var6,
330  const RooAbsArg& var7, const RooAbsArg& var8,
331  const RooAbsArg& var9, const char *name) :
332  RooAbsCollection(name)
333 {
334  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7); add(var8); add(var9);
335  TRACE_CREATE
336 }
337 
338 
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Constructor from a root TCollection. Elements in the collection that
342 /// do not inherit from RooAbsArg will be skipped. A warning message
343 /// will be printed for every skipped item.
344 
345 RooArgSet::RooArgSet(const TCollection& tcoll, const char* name) :
346  RooAbsCollection(name)
347 {
348  TIterator* iter = tcoll.MakeIterator() ;
349  TObject* obj ;
350  while((obj=iter->Next())) {
351  if (!dynamic_cast<RooAbsArg*>(obj)) {
352  coutW(InputArguments) << "RooArgSet::RooArgSet(TCollection) element " << obj->GetName()
353  << " is not a RooAbsArg, ignored" << endl ;
354  continue ;
355  }
356  add(*(RooAbsArg*)obj) ;
357  }
358  delete iter ;
359  TRACE_CREATE
360 }
361 
362 
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Copy constructor. Note that a copy of a set is always non-owning,
366 /// even the source set is owning. To create an owning copy of
367 /// a set (owning or not), use the snaphot() method.
368 
369 RooArgSet::RooArgSet(const RooArgSet& other, const char *name)
370  : RooAbsCollection(other,name)
371 {
372  TRACE_CREATE
373 }
374 
375 
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// Destructor
379 
380 RooArgSet::~RooArgSet()
381 {
382  TRACE_DESTROY
383 }
384 
385 
386 
387 ////////////////////////////////////////////////////////////////////////////////
388 /// Add element to non-owning set. The operation will fail if
389 /// a similarly named object already exists in the set, or
390 /// the set is specified to own its elements. Eventual error messages
391 /// can be suppressed with the silent flag
392 
393 Bool_t RooArgSet::add(const RooAbsArg& var, Bool_t silent)
394 {
395  return checkForDup(var,silent)? kFALSE : RooAbsCollection::add(var,silent) ;
396 }
397 
398 
399 
400 ////////////////////////////////////////////////////////////////////////////////
401 /// Add element to an owning set. The operation will fail if
402 /// a similarly named object already exists in the set, or
403 /// the set is not specified to own its elements. Eventual error messages
404 /// can be suppressed with the silent flag
405 
406 Bool_t RooArgSet::addOwned(RooAbsArg& var, Bool_t silent)
407 {
408  return checkForDup(var,silent)? kFALSE : RooAbsCollection::addOwned(var,silent) ;
409 }
410 
411 
412 
413 ////////////////////////////////////////////////////////////////////////////////
414 /// Add clone of specified element to an owning set. If sucessful, the
415 /// set will own the clone, not the original. The operation will fail if
416 /// a similarly named object already exists in the set, or
417 /// the set is not specified to own its elements. Eventual error messages
418 /// can be suppressed with the silent flag
419 
420 RooAbsArg* RooArgSet::addClone(const RooAbsArg& var, Bool_t silent)
421 {
422  return checkForDup(var,silent)? 0 : RooAbsCollection::addClone(var,silent) ;
423 }
424 
425 
426 
427 ////////////////////////////////////////////////////////////////////////////////
428 /// Array operator. Named element must exist in set, otherwise
429 /// code will abort.
430 ///
431 /// When used as lvalue in assignment operations, the element contained in
432 /// the list will not be changed, only the value of the existing element!
433 
434 RooAbsArg& RooArgSet::operator[](const char* name) const
435 {
436  RooAbsArg* arg = find(name) ;
437  if (!arg) {
438  coutE(InputArguments) << "RooArgSet::operator[](" << GetName() << ") ERROR: no element named " << name << " in set" << endl ;
439  RooErrorHandler::softAbort() ;
440  }
441  return *arg ;
442 }
443 
444 
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Check if element with var's name is already in set
448 
449 Bool_t RooArgSet::checkForDup(const RooAbsArg& var, Bool_t silent) const
450 {
451  RooAbsArg *other = find(var);
452  if (other) {
453  if (other != &var) {
454  if (!silent) {
455  // print a warning if this variable is not the same one we
456  // already have
457  coutE(InputArguments) << "RooArgSet::checkForDup: ERROR argument with name " << var.GetName() << " is already in this set" << endl;
458  }
459  }
460  // don't add duplicates
461  return kTRUE;
462  }
463  return kFALSE ;
464 }
465 
466 
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Get value of a RooAbsReal stored in set with given name. If none is found, value of defVal is returned.
470 /// No error messages are printed unless the verbose flag is set
471 
472 Double_t RooArgSet::getRealValue(const char* name, Double_t defVal, Bool_t verbose) const
473 {
474  RooAbsArg* raa = find(name) ;
475  if (!raa) {
476  if (verbose) coutE(InputArguments) << "RooArgSet::getRealValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
477  return defVal ;
478  }
479  RooAbsReal* rar = dynamic_cast<RooAbsReal*>(raa) ;
480  if (!rar) {
481  if (verbose) coutE(InputArguments) << "RooArgSet::getRealValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsReal" << endl ;
482  return defVal ;
483  }
484  return rar->getVal() ;
485 }
486 
487 
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 /// Set value of a RooAbsRealLValye stored in set with given name to newVal
491 /// No error messages are printed unless the verbose flag is set
492 
493 Bool_t RooArgSet::setRealValue(const char* name, Double_t newVal, Bool_t verbose)
494 {
495  RooAbsArg* raa = find(name) ;
496  if (!raa) {
497  if (verbose) coutE(InputArguments) << "RooArgSet::setRealValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
498  return kTRUE ;
499  }
500  RooAbsRealLValue* rar = dynamic_cast<RooAbsRealLValue*>(raa) ;
501  if (!rar) {
502  if (verbose) coutE(InputArguments) << "RooArgSet::setRealValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsRealLValue" << endl ;
503  return kTRUE;
504  }
505  rar->setVal(newVal) ;
506  return kFALSE ;
507 }
508 
509 
510 
511 ////////////////////////////////////////////////////////////////////////////////
512 /// Get state name of a RooAbsCategory stored in set with given name. If none is found, value of defVal is returned.
513 /// No error messages are printed unless the verbose flag is set
514 
515 const char* RooArgSet::getCatLabel(const char* name, const char* defVal, Bool_t verbose) const
516 {
517  RooAbsArg* raa = find(name) ;
518  if (!raa) {
519  if (verbose) coutE(InputArguments) << "RooArgSet::getCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
520  return defVal ;
521  }
522  RooAbsCategory* rac = dynamic_cast<RooAbsCategory*>(raa) ;
523  if (!rac) {
524  if (verbose) coutE(InputArguments) << "RooArgSet::getCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
525  return defVal ;
526  }
527  return rac->getLabel() ;
528 }
529 
530 
531 
532 ////////////////////////////////////////////////////////////////////////////////
533 /// Set state name of a RooAbsCategoryLValue stored in set with given name to newVal.
534 /// No error messages are printed unless the verbose flag is set
535 
536 Bool_t RooArgSet::setCatLabel(const char* name, const char* newVal, Bool_t verbose)
537 {
538  RooAbsArg* raa = find(name) ;
539  if (!raa) {
540  if (verbose) coutE(InputArguments) << "RooArgSet::setCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
541  return kTRUE ;
542  }
543  RooAbsCategoryLValue* rac = dynamic_cast<RooAbsCategoryLValue*>(raa) ;
544  if (!rac) {
545  if (verbose) coutE(InputArguments) << "RooArgSet::setCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
546  return kTRUE ;
547  }
548  rac->setLabel(newVal) ;
549  return kFALSE ;
550 }
551 
552 
553 
554 ////////////////////////////////////////////////////////////////////////////////
555 /// Get index value of a RooAbsCategory stored in set with given name. If none is found, value of defVal is returned.
556 /// No error messages are printed unless the verbose flag is set
557 
558 Int_t RooArgSet::getCatIndex(const char* name, Int_t defVal, Bool_t verbose) const
559 {
560  RooAbsArg* raa = find(name) ;
561  if (!raa) {
562  if (verbose) coutE(InputArguments) << "RooArgSet::getCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
563  return defVal ;
564  }
565  RooAbsCategory* rac = dynamic_cast<RooAbsCategory*>(raa) ;
566  if (!rac) {
567  if (verbose) coutE(InputArguments) << "RooArgSet::getCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
568  return defVal ;
569  }
570  return rac->getIndex() ;
571 }
572 
573 
574 
575 ////////////////////////////////////////////////////////////////////////////////
576 /// Set index value of a RooAbsCategoryLValue stored in set with given name to newVal.
577 /// No error messages are printed unless the verbose flag is set
578 
579 Bool_t RooArgSet::setCatIndex(const char* name, Int_t newVal, Bool_t verbose)
580 {
581  RooAbsArg* raa = find(name) ;
582  if (!raa) {
583  if (verbose) coutE(InputArguments) << "RooArgSet::setCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
584  return kTRUE ;
585  }
586  RooAbsCategoryLValue* rac = dynamic_cast<RooAbsCategoryLValue*>(raa) ;
587  if (!rac) {
588  if (verbose) coutE(InputArguments) << "RooArgSet::setCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
589  return kTRUE ;
590  }
591  rac->setIndex(newVal) ;
592  return kFALSE ;
593 }
594 
595 
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 /// Get string value of a RooAbsString stored in set with given name. If none is found, value of defVal is returned.
599 /// No error messages are printed unless the verbose flag is set
600 
601 const char* RooArgSet::getStringValue(const char* name, const char* defVal, Bool_t verbose) const
602 {
603  RooAbsArg* raa = find(name) ;
604  if (!raa) {
605  if (verbose) coutE(InputArguments) << "RooArgSet::getStringValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
606  return defVal ;
607  }
608  RooAbsString* ras = dynamic_cast<RooAbsString*>(raa) ;
609  if (!ras) {
610  if (verbose) coutE(InputArguments) << "RooArgSet::getStringValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsString" << endl ;
611  return defVal ;
612  }
613  return ras->getVal() ;
614 }
615 
616 
617 
618 ////////////////////////////////////////////////////////////////////////////////
619 /// Set string value of a RooStringVar stored in set with given name to newVal.
620 /// No error messages are printed unless the verbose flag is set
621 
622 Bool_t RooArgSet::setStringValue(const char* name, const char* newVal, Bool_t verbose)
623 {
624  RooAbsArg* raa = find(name) ;
625  if (!raa) {
626  if (verbose) coutE(InputArguments) << "RooArgSet::setStringValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
627  return kTRUE ;
628  }
629  RooStringVar* ras = dynamic_cast<RooStringVar*>(raa) ;
630  if (!ras) {
631  if (verbose) coutE(InputArguments) << "RooArgSet::setStringValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsString" << endl ;
632  return kTRUE ;
633  }
634  ras->setVal(newVal) ;
635  return kFALSE ;
636 }
637 
638 
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Write contents of the argset to specified file.
642 /// See writeToStream() for details
643 
644 void RooArgSet::writeToFile(const char* fileName) const
645 {
646  ofstream ofs(fileName) ;
647  if (ofs.fail()) {
648  coutE(InputArguments) << "RooArgSet::writeToFile(" << GetName() << ") error opening file " << fileName << endl ;
649  return ;
650  }
651  writeToStream(ofs,kFALSE) ;
652 }
653 
654 
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// Read contents of the argset from specified file.
658 /// See readFromStream() for details
659 
660 Bool_t RooArgSet::readFromFile(const char* fileName, const char* flagReadAtt, const char* section, Bool_t verbose)
661 {
662  ifstream ifs(fileName) ;
663  if (ifs.fail()) {
664  coutE(InputArguments) << "RooArgSet::readFromFile(" << GetName() << ") error opening file " << fileName << endl ;
665  return kTRUE ;
666  }
667  return readFromStream(ifs,kFALSE,flagReadAtt,section,verbose) ;
668 }
669 
670 
671 
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Write the contents of the argset in ASCII form to given stream.
675 ///
676 /// A line is written for each element contained in the form
677 /// `<argName> = <argValue>`
678 ///
679 /// The `<argValue>` part of each element is written by the arguments'
680 /// writeToStream() function.
681 /// \param os The stream to write to.
682 /// \param compact Write only the bare values, separated by ' '.
683 /// \note In compact mode, the stream cannot be read back into a RooArgSet,
684 /// but only into a RooArgList, because the variable names are lost.
685 /// \param section If non-null, add a section header like `[<section>]`.
686 void RooArgSet::writeToStream(ostream& os, Bool_t compact, const char* section) const
687 {
688  if (section && section[0] != '\0')
689  os << '[' << section << ']' << '\n';
690 
691  if (compact) {
692  for (const auto next : _list) {
693  next->writeToStream(os, true);
694  os << " ";
695  }
696  os << endl;
697  } else {
698  for (const auto next : _list) {
699  os << next->GetName() << " = " ;
700  next->writeToStream(os,kFALSE) ;
701  os << endl ;
702  }
703  }
704 }
705 
706 
707 
708 
709 ////////////////////////////////////////////////////////////////////////////////
710 /// Read the contents of the argset in ASCII form from given stream.
711 ///
712 /// The stream is read to end-of-file and each line is assumed to be
713 /// of the form
714 /// \code
715 /// <argName> = <argValue>
716 /// \endcode
717 /// Lines starting with argNames not matching any element in the list
718 /// will be ignored with a warning message. In addition limited C++ style
719 /// preprocessing and flow control is provided. The following constructions
720 /// are recognized:
721 /// \code
722 /// include "include.file"
723 /// \endcode
724 /// Include given file, recursive inclusion OK
725 /// \code
726 /// if (<boolean_expression>)
727 /// <name> = <value>
728 /// ....
729 /// else if (<boolean_expression>)
730 /// ....
731 /// else
732 /// ....
733 /// endif
734 /// \endcode
735 ///
736 /// All expressions are evaluated by RooFormula, and may involve any of
737 /// the sets variables.
738 /// \code
739 /// echo <Message>
740 /// \endcode
741 /// Print console message while reading from stream
742 /// \code
743 /// abort
744 /// \endcode
745 /// Force termination of read sequence with error status
746 ///
747 /// The value of each argument is read by the arguments readFromStream
748 /// function.
749 
750 Bool_t RooArgSet::readFromStream(istream& is, Bool_t compact, const char* flagReadAtt, const char* section, Bool_t verbose)
751 {
752  if (compact) {
753  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << ") compact mode not supported" << endl ;
754  return kTRUE ;
755  }
756 
757  RooStreamParser parser(is) ;
758  parser.setPunctuation("=") ;
759  TString token ;
760  Bool_t retVal(kFALSE) ;
761 
762  // Conditional stack and related state variables
763  // coverity[UNINIT]
764  Bool_t anyCondTrue[100] ;
765  Bool_t condStack[100] ;
766  Bool_t lastLineWasElse=kFALSE ;
767  Int_t condStackLevel=0 ;
768  condStack[0]=kTRUE ;
769 
770  // Prepare section processing
771  TString sectionHdr("[") ;
772  if (section) sectionHdr.Append(section) ;
773  sectionHdr.Append("]") ;
774  Bool_t inSection(section?kFALSE:kTRUE) ;
775 
776  Bool_t reprocessToken = kFALSE ;
777  while (1) {
778 
779  if (is.eof() || is.fail() || parser.atEOF()) {
780  break ;
781  }
782 
783  // Read next token until memEnd of file
784  if (!reprocessToken) {
785  token = parser.readToken() ;
786  }
787  reprocessToken = kFALSE ;
788 
789  // Skip empty lines
790  if (token.IsNull()) {
791  continue ;
792  }
793 
794  // Process include directives
795  if (!token.CompareTo("include")) {
796  if (parser.atEOL()) {
797  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName()
798  << "): no filename found after include statement" << endl ;
799  return kTRUE ;
800  }
801  TString filename = parser.readLine() ;
802  ifstream incfs(filename) ;
803  if (!incfs.good()) {
804  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): cannot open include file " << filename << endl ;
805  return kTRUE ;
806  }
807  coutI(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): processing include file "
808  << filename << endl ;
809  if (readFromStream(incfs,compact,flagReadAtt,inSection?0:section,verbose)) return kTRUE ;
810  continue ;
811  }
812 
813  // Process section headers if requested
814  if (*token.Data()=='[') {
815  TString hdr(token) ;
816  const char* last = token.Data() + token.Length() -1 ;
817  if (*last != ']') {
818  hdr.Append(" ") ;
819  hdr.Append(parser.readLine()) ;
820  }
821 // parser.putBackToken(token) ;
822 // token = parser.readLine() ;
823  if (section) {
824  inSection = !sectionHdr.CompareTo(hdr) ;
825  }
826  continue ;
827  }
828 
829  // If section is specified, ignore all data outside specified section
830  if (!inSection) {
831  parser.zapToEnd(kTRUE) ;
832  continue ;
833  }
834 
835  // Conditional statement evaluation
836  if (!token.CompareTo("if")) {
837 
838  // Extract conditional expressions and check validity
839  TString expr = parser.readLine() ;
840  RooFormula form(expr,expr,*this) ;
841  if (!form.ok()) return kTRUE ;
842 
843  // Evaluate expression
844  Bool_t status = form.eval()?kTRUE:kFALSE ;
845  if (lastLineWasElse) {
846  anyCondTrue[condStackLevel] |= status ;
847  lastLineWasElse=kFALSE ;
848  } else {
849  condStackLevel++ ;
850  anyCondTrue[condStackLevel] = status ;
851  }
852  condStack[condStackLevel] = status ;
853 
854  if (verbose) cxcoutD(Eval) << "RooArgSet::readFromStream(" << GetName()
855  << "): conditional expression " << expr << " = "
856  << (condStack[condStackLevel]?"true":"false") << endl ;
857  continue ; // go to next line
858  }
859 
860  if (!token.CompareTo("else")) {
861  // Must have seen an if statement before
862  if (condStackLevel==0) {
863  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'else'" << endl ;
864  }
865 
866  if (parser.atEOL()) {
867  // simple else: process if nothing else was true
868  condStack[condStackLevel] = !anyCondTrue[condStackLevel] ;
869  parser.zapToEnd(kFALSE) ;
870  continue ;
871  } else {
872  // if anything follows it should be 'if'
873  token = parser.readToken() ;
874  if (token.CompareTo("if")) {
875  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): syntax error: 'else " << token << "'" << endl ;
876  return kTRUE ;
877  } else {
878  if (anyCondTrue[condStackLevel]) {
879  // No need for further checking, true conditional already processed
880  condStack[condStackLevel] = kFALSE ;
881  parser.zapToEnd(kFALSE) ;
882  continue ;
883  } else {
884  // Process as normal 'if' no true conditional was encountered
885  reprocessToken = kTRUE ;
886  lastLineWasElse=kTRUE ;
887  continue ;
888  }
889  }
890  }
891  }
892 
893  if (!token.CompareTo("endif")) {
894  // Must have seen an if statement before
895  if (condStackLevel==0) {
896  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'endif'" << endl ;
897  return kTRUE ;
898  }
899 
900  // Decrease stack by one
901  condStackLevel-- ;
902  continue ;
903  }
904 
905  // If current conditional is true
906  if (condStack[condStackLevel]) {
907 
908  // Process echo statements
909  if (!token.CompareTo("echo")) {
910  TString message = parser.readLine() ;
911  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): >> " << message << endl ;
912  continue ;
913  }
914 
915  // Process abort statements
916  if (!token.CompareTo("abort")) {
917  TString message = parser.readLine() ;
918  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): USER ABORT" << endl ;
919  return kTRUE ;
920  }
921 
922  // Interpret the rest as <arg> = <value_expr>
923  RooAbsArg *arg ;
924 
925  if ((arg = find(token)) && !arg->getAttribute("Dynamic")) {
926  if (parser.expectToken("=",kTRUE)) {
927  parser.zapToEnd(kTRUE) ;
928  retVal=kTRUE ;
929  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName()
930  << "): missing '=' sign: " << arg << endl ;
931  continue ;
932  }
933  Bool_t argRet = arg->readFromStream(is,kFALSE,verbose) ;
934  if (!argRet && flagReadAtt) arg->setAttribute(flagReadAtt,kTRUE) ;
935  retVal |= argRet ;
936  } else {
937  if (verbose) {
938  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): argument "
939  << token << " not in list, ignored" << endl ;
940  }
941  parser.zapToEnd(kTRUE) ;
942  }
943  } else {
944  parser.readLine() ;
945  }
946  }
947 
948  // Did we fully unwind the conditional stack?
949  if (condStackLevel!=0) {
950  coutE(InputArguments) << "RooArgSet::readFromStream(" << GetName() << "): missing 'endif'" << endl ;
951  return kTRUE ;
952  }
953 
954  return retVal ;
955 }
956 
957 
958 Bool_t RooArgSet::isInRange(const char* rangeSpec)
959 {
960  char buf[1024] ;
961  strlcpy(buf,rangeSpec,1024) ;
962  char* token = strtok(buf,",") ;
963 
964  TIterator* iter = createIterator() ;
965 
966  while(token) {
967 
968  Bool_t accept=kTRUE ;
969  iter->Reset() ;
970  RooAbsArg* arg ;
971  while((arg=(RooAbsArg*)iter->Next())) {
972  RooAbsRealLValue* lvarg = dynamic_cast<RooAbsRealLValue*>(arg) ;
973  if (lvarg) {
974  if (!lvarg->inRange(token)) {
975  accept=kFALSE ;
976  break ;
977  }
978  }
979  // WVE MUST HANDLE RooAbsCategoryLValue ranges as well
980  }
981  if (accept) {
982  delete iter ;
983  return kTRUE ;
984  }
985 
986  token = strtok(0,",") ;
987  }
988 
989  delete iter ;
990  return kFALSE ;
991 }