/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id: RooArgSet.cc,v 1.61 2005/06/21 19:59:51 wverkerke Exp $
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

// -- CLASS DESCRIPTION [CONT] --
// RooArgSet is a container object that can hold multiple RooAbsArg objects.
// The container has set semantics which means that:
//
//  - Every object it contains must have a unique name returned by GetName().
//
//  - Contained objects are not ordered, although the set can be traversed
//    using an iterator returned by createIterator(). The iterator does not
//    necessarily follow the object insertion order.
//
//  - Objects can be retrieved by name only, and not by index.
//
//
// Ownership of contents. 
//
// Unowned objects are inserted with the add() method. Owned objects
// are added with addOwned() or addClone(). A RooArgSet either owns all 
// of it contents, or none, which is determined by the first <add>
// call. Once an ownership status is selected, inappropriate <add> calls
// will return error status. Clearing the list via removeAll() resets the 
// ownership status. Arguments supplied in the constructor are always added 
// as unowned elements.
//
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <iomanip>
#include <fstream>
#include "TClass.h"
#include "RooArgSet.h"
#include "RooStreamParser.h"
#include "RooFormula.h"
#include "RooAbsRealLValue.h"
#include "RooAbsCategoryLValue.h"
#include "RooStringVar.h"
#include "RooTrace.h"
#include "RooArgList.h"

#if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
char* operator+( streampos&, char* );
#endif

ClassImp(RooArgSet)
  ;

 RooArgSet::RooArgSet() :
  RooAbsCollection()
{
  // Default constructor
}

 RooArgSet::RooArgSet(const RooArgList& list) :
  RooAbsCollection(list.GetName())
{
  // Constructor from a RooArgList. If the list contains multiple
  // objects with the same name, only the first is store in the set.
  // Warning messages will be printed for dropped items.

  add(list,kTRUE) ; // verbose to catch duplicate errors
}


 RooArgSet::RooArgSet(const char *name) :
  RooAbsCollection(name)
{
  // Empty set constructor
}

 RooArgSet::RooArgSet(const RooAbsArg& var1,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 1 initial object

  add(var1);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 2 initial objects

  add(var1); add(var2);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 3 initial objects

  add(var1); add(var2); add(var3);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3, const RooAbsArg& var4,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 4 initial objects

  add(var1); add(var2); add(var3); add(var4);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1,
		     const RooAbsArg& var2, const RooAbsArg& var3,
		     const RooAbsArg& var4, const RooAbsArg& var5,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 5 initial objects

  add(var1); add(var2); add(var3); add(var4); add(var5);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3, const RooAbsArg& var4, 
		     const RooAbsArg& var5, const RooAbsArg& var6,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 6 initial objects

  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6);
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3, const RooAbsArg& var4, 
		     const RooAbsArg& var5, const RooAbsArg& var6, 
		     const RooAbsArg& var7,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 7 initial objects

  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7) ;
}

 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3, const RooAbsArg& var4, 
		     const RooAbsArg& var5, const RooAbsArg& var6, 
		     const RooAbsArg& var7, const RooAbsArg& var8,
		     const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 8 initial objects

  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7) ;add(var8) ;
}


 RooArgSet::RooArgSet(const RooAbsArg& var1, const RooAbsArg& var2, 
		     const RooAbsArg& var3, const RooAbsArg& var4, 
		     const RooAbsArg& var5, const RooAbsArg& var6, 
		     const RooAbsArg& var7, const RooAbsArg& var8,
		     const RooAbsArg& var9, const char *name) :
  RooAbsCollection(name)
{
  // Constructor for set containing 9 initial objects

  add(var1); add(var2); add(var3); add(var4); add(var5); add(var6); add(var7); add(var8); add(var9);
}



 RooArgSet::RooArgSet(const TCollection& tcoll, const char* name) :
  RooAbsCollection(name)
{
  // Constructor from a root TCollection. Elements in the collection that
  // do not inherit from RooAbsArg will be skipped. A warning message
  // will be printed for every skipped item.

  TIterator* iter = tcoll.MakeIterator() ;
  TObject* obj ;
  while((obj=iter->Next())) {
    if (!dynamic_cast<RooAbsArg*>(obj)) {
      cout << "RooArgSet::RooArgSet(TCollection) element " << obj->GetName() 
	   << " is not a RooAbsArg, ignored" << endl ;
      continue ;
    }
    add(*(RooAbsArg*)obj) ;
  }
  delete iter ;
}



 RooArgSet::RooArgSet(const RooArgSet& other, const char *name) 
  : RooAbsCollection(other,name)
{
  // Copy constructor. Note that a copy of a set is always non-owning,
  // even the source set is owning. To create an owning copy of
  // a set (owning or not), use the snaphot() method.
}



 RooArgSet::~RooArgSet() 
{
  // Destructor
}



 Bool_t RooArgSet::add(const RooAbsArg& var, Bool_t silent) 
{
  // Add element to non-owning set. The operation will fail if
  // a similarly named object already exists in the set, or
  // the set is specified to own its elements. Eventual error messages
  // can be suppressed with the silent flag
  return checkForDup(var,silent)? kFALSE : RooAbsCollection::add(var,silent) ;
}


 Bool_t RooArgSet::addOwned(RooAbsArg& var, Bool_t silent)
{
  // Add element to an owning set. The operation will fail if
  // a similarly named object already exists in the set, or
  // the set is not specified to own its elements. Eventual error messages
  // can be suppressed with the silent flag
  return checkForDup(var,silent)? kFALSE : RooAbsCollection::addOwned(var,silent) ;
}


 RooAbsArg* RooArgSet::addClone(const RooAbsArg& var, Bool_t silent) 
{
  // Add clone of specified element to an owning set. If sucessful, the
  // set will own the clone, not the original. The operation will fail if
  // a similarly named object already exists in the set, or
  // the set is not specified to own its elements. Eventual error messages
  // can be suppressed with the silent flag
  return checkForDup(var,silent)? 0 : RooAbsCollection::addClone(var,silent) ;
}



RooAbsArg& RooArgSet::operator[](const char* name) const 
{     
  // Array operator. Named element must exist in set, otherwise
  // code will abort. 
  //
  // When used as lvalue in assignment operations, the element contained in
  // the list will not be changed, only the value of the existing element!
  RooAbsArg* arg = find(name) ;
  if (!arg) {
    cout << "RooArgSet::operator[](" << GetName() << ") ERROR: no element named " << name << " in set" << endl ;
    RooErrorHandler::softAbort() ;
  }
  return *arg ; 
}



 Bool_t RooArgSet::checkForDup(const RooAbsArg& var, Bool_t silent) const 
{
  // Check if element with var's name is already in set

  RooAbsArg *other = 0;
  if((other= find(var.GetName()))) {
    if(other != &var) {
      if (!silent)
	// print a warning if this variable is not the same one we
	// already have
	cout << ClassName() << "::" << GetName() << "::checkForDup: cannot add second copy of argument \""
	     << var.GetName() << "\"" << endl;
    }
    // don't add duplicates
    return kTRUE;
  }

  return kFALSE ;
}


 Double_t RooArgSet::getRealValue(const char* name, Double_t defVal, Bool_t verbose) const
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::getRealValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return defVal ;
  }
  RooAbsReal* rar = dynamic_cast<RooAbsReal*>(raa) ;
  if (!rar) {
    if (verbose) cout << "RooArgSet::getRealValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsReal" << endl ;
    return defVal ;
  }
  return rar->getVal() ;
}


 Bool_t RooArgSet::setRealValue(const char* name, Double_t newVal, Bool_t verbose) 
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::setRealValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return kTRUE ;
  }
  RooAbsRealLValue* rar = dynamic_cast<RooAbsRealLValue*>(raa) ;
  if (!rar) {
    if (verbose) cout << "RooArgSet::setRealValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsRealLValue" << endl ;
    return kTRUE;
  }
  rar->setVal(newVal) ;
  return kFALSE ;
}



 const char* RooArgSet::getCatLabel(const char* name, const char* defVal, Bool_t verbose) const
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::getCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return defVal ;
  }
  RooAbsCategory* rac = dynamic_cast<RooAbsCategory*>(raa) ;
  if (!rac) {
    if (verbose) cout << "RooArgSet::getCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
    return defVal ;
  }
  return rac->getLabel() ;
}


 Bool_t RooArgSet::setCatLabel(const char* name, const char* newVal, Bool_t verbose) 
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::setCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return kTRUE ;
  }
  RooAbsCategoryLValue* rac = dynamic_cast<RooAbsCategoryLValue*>(raa) ;
  if (!rac) {
    if (verbose) cout << "RooArgSet::setCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
    return kTRUE ;
  }
  rac->setLabel(newVal) ;
  return kFALSE ;
}


 Int_t RooArgSet::getCatIndex(const char* name, Int_t defVal, Bool_t verbose) const
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::getCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return defVal ;
  }
  RooAbsCategory* rac = dynamic_cast<RooAbsCategory*>(raa) ;
  if (!rac) {
    if (verbose) cout << "RooArgSet::getCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
    return defVal ;
  }
  return rac->getIndex() ;
}


 Bool_t RooArgSet::setCatIndex(const char* name, Int_t newVal, Bool_t verbose) 
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::setCatLabel(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return kTRUE ;
  }
  RooAbsCategoryLValue* rac = dynamic_cast<RooAbsCategoryLValue*>(raa) ;
  if (!rac) {
    if (verbose) cout << "RooArgSet::setCatLabel(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsCategory" << endl ;
    return kTRUE ;
  }
  rac->setIndex(newVal) ;
  return kFALSE ;
}


 const char* RooArgSet::getStringValue(const char* name, const char* defVal, Bool_t verbose) const
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::getStringValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return defVal ;
  }
  RooAbsString* ras = dynamic_cast<RooAbsString*>(raa) ;
  if (!ras) {
    if (verbose) cout << "RooArgSet::getStringValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsString" << endl ;
    return defVal ;
  }
  return ras->getVal() ;
}


 Bool_t RooArgSet::setStringValue(const char* name, const char* newVal, Bool_t verbose) 
{
  RooAbsArg* raa = find(name) ;
  if (!raa) {
    if (verbose) cout << "RooArgSet::setStringValue(" << GetName() << ") ERROR no object with name '" << name << "' found" << endl ;
    return kTRUE ;
  }
  RooStringVar* ras = dynamic_cast<RooStringVar*>(raa) ;
  if (!ras) {
    if (verbose) cout << "RooArgSet::setStringValue(" << GetName() << ") ERROR object '" << name << "' is not of type RooAbsString" << endl ;
    return kTRUE ;
  }
  ras->setVal(newVal) ;
  return kFALSE ;
}



 void RooArgSet::writeToFile(const char* fileName) 
{
  // Write contents of the argset to specified file.
  // See writeToStream() for details
  ofstream ofs(fileName) ;
  if (ofs.fail()) {
    cout << "RooArgSet::writeToFile(" << GetName() << ") error opening file " << fileName << endl ;
    return ;
  }
  writeToStream(ofs,kFALSE) ;
}




 Bool_t RooArgSet::readFromFile(const char* fileName, const char* flagReadAtt, const char* section, Bool_t verbose) 
{
  // Read contents of the argset from specified file.
  // See readFromStream() for details
  ifstream ifs(fileName) ;
  if (ifs.fail()) {
    cout << "RooArgSet::readFromFile(" << GetName() << ") error opening file " << fileName << endl ;
    return kTRUE ;
  }
  return readFromStream(ifs,kFALSE,flagReadAtt,section,verbose) ;
}



 void RooArgSet::writeToStream(ostream& os, Bool_t compact, const char* /*section*/) 
{
  // Write the contents of the argset in ASCII form to given stream.
  // 
  // A line is written for each element contained in the form
  // <argName> = <argValue>
  // 
  // The <argValue> part of each element is written by the arguments' 
  // writeToStream() function.

  if (compact) {
    cout << "RooArgSet::writeToStream(" << GetName() << ") compact mode not supported" << endl ;
    return ;
  }

  TIterator *iterator= createIterator();
  RooAbsArg *next = 0;
  while((0 != (next= (RooAbsArg*)iterator->Next()))) {
    os << next->GetName() << " = " ;
    next->writeToStream(os,kFALSE) ;
    os << endl ;
  }
  delete iterator;  
}




 Bool_t RooArgSet::readFromStream(istream& is, Bool_t compact, const char* flagReadAtt, const char* section, Bool_t verbose) 
{
  // Read the contents of the argset in ASCII form from given stream.
  // 
  // The stream is read to end-of-file and each line is assumed to be
  // of the form
  //
  // <argName> = <argValue>
  // 
  // Lines starting with argNames not matching any element in the list
  // will be ignored with a warning message. In addition limited C++ style 
  // preprocessing and flow control is provided. The following constructions 
  // are recognized:
  //
  // > #include "include.file"       
  // 
  // Include given file, recursive inclusion OK
  // 
  // > if (<boolean_expression>)
  // >   <name> = <value>
  // >   ....
  // > else if (<boolean_expression>)
  //     ....
  // > else
  //     ....
  // > endif
  //
  // All expressions are evaluated by RooFormula, and may involve any of
  // the sets variables. 
  //
  // > echo <Message>
  //
  // Print console message while reading from stream
  //
  // > abort
  //
  // Force termination of read sequence with error status 
  //
  // The value of each argument is read by the arguments readFromStream
  // function.

  if (compact) {
    cout << "RooArgSet::readFromStream(" << GetName() << ") compact mode not supported" << endl ;
    return kTRUE ;
  }

  RooStreamParser parser(is) ;
  parser.setPunctuation("=") ;
  TString token ;
  Bool_t retVal(kFALSE) ;
  
  // Conditional stack and related state variables
  Bool_t anyCondTrue[100] ;
  Bool_t condStack[100] ;
  Bool_t lastLineWasElse=kFALSE ;
  Int_t condStackLevel=0 ;
  condStack[0]=kTRUE ;
  
  // Prepare section processing
  TString sectionHdr("[") ;
  if (section) sectionHdr.Append(section) ;
  sectionHdr.Append("]") ;
  Bool_t inSection(section?kFALSE:kTRUE) ;

  Bool_t reprocessToken = kFALSE ;
  while (1) {

    if (is.eof() || is.fail() || parser.atEOF()) {
      break ;
    }
    
    // Read next token until end of file
    if (!reprocessToken) {
      token = parser.readToken() ;
    }
    reprocessToken = kFALSE ;

    // Skip empty lines 
    if (token.IsNull()) {
      continue ;
    }

    // Process include directives
    if (!token.CompareTo("include")) {
      if (parser.atEOL()) {
	cout << "RooArgSet::readFromStream(" << GetName() 
	     << "): no filename found after include statement" << endl ;
	return kTRUE ;
      }
      TString filename = parser.readLine() ;
      ifstream incfs(filename) ;
      if (!incfs.good()) {
	cout << "RooArgSet::readFromStream(" << GetName() << "): cannot open include file " << filename << endl ;
	return kTRUE ;
      }
      if (verbose) {
	cout << "RooArgSet::readFromStream(" << GetName() << "): processing include file " 
	     << filename << endl ;
      }
      if (readFromStream(incfs,compact,flagReadAtt,inSection?0:section,verbose)) return kTRUE ;
      continue ;
    }

    // Process section headers if requested
    if (*token.Data()=='[') {
      TString hdr(token) ;
      const char* last = token.Data() + token.Length() -1 ;
      if (*last != ']') {
	hdr.Append(" ") ;
	hdr.Append(parser.readLine()) ;
      }
//       parser.putBackToken(token) ;
//       token = parser.readLine() ;
      if (section) {
	inSection = !sectionHdr.CompareTo(hdr) ;
      }
      continue ;
    }

    // If section is specified, ignore all data outside specified section
    if (!inSection) {
      parser.zapToEnd(kTRUE) ;
      continue ;
    }

    // Conditional statement evaluation
    if (!token.CompareTo("if")) {
      
      // Extract conditional expressions and check validity
      TString expr = parser.readLine() ;
      RooFormula form(expr,expr,*this) ;
      if (!form.ok()) return kTRUE ;
      
      // Evaluate expression
      Bool_t status = form.eval()?kTRUE:kFALSE ;
      if (lastLineWasElse) {
	anyCondTrue[condStackLevel] |= status ;
	lastLineWasElse=kFALSE ;
      } else {
	condStackLevel++ ;
	anyCondTrue[condStackLevel] = status ;
      }
      condStack[condStackLevel] = status ;
      
      if (verbose) cout << "RooArgSet::readFromStream(" << GetName() 
			<< "): conditional expression " << expr << " = " 
			<< (condStack[condStackLevel]?"true":"false") << endl ;
      continue ; // go to next line
    }
    
    if (!token.CompareTo("else")) {
      // Must have seen an if statement before
      if (condStackLevel==0) {
	cout << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'else'" << endl ;
      }
      
      if (parser.atEOL()) {
	// simple else: process if nothing else was true
	condStack[condStackLevel] = !anyCondTrue[condStackLevel] ; 
	parser.zapToEnd(kFALSE) ;
	continue ;
      } else {
	// if anything follows it should be 'if'
	token = parser.readToken() ;
	if (token.CompareTo("if")) {
	  cout << "RooArgSet::readFromStream(" << GetName() << "): syntax error: 'else " << token << "'" << endl ;
	  return kTRUE ;
	} else {
	  if (anyCondTrue[condStackLevel]) {
	    // No need for further checking, true conditional already processed
	    condStack[condStackLevel] = kFALSE ;
	    parser.zapToEnd(kFALSE) ;
	    continue ;
	  } else {
	    // Process as normal 'if' no true conditional was encountered 
	    reprocessToken = kTRUE ;
	    lastLineWasElse=kTRUE ;
	    continue ;
	  }
	}
      }	
    }
    
    if (!token.CompareTo("endif")) {
      // Must have seen an if statement before
      if (condStackLevel==0) {
	cout << "RooArgSet::readFromStream(" << GetName() << "): unmatched 'endif'" << endl ;
	return kTRUE ;
      }
      
      // Decrease stack by one
      condStackLevel-- ;
      continue ;
    } 
    
    // If current conditional is true
    if (condStack[condStackLevel]) {
      
      // Process echo statements
      if (!token.CompareTo("echo")) {
	TString message = parser.readLine() ;
	cout << "RooArgSet::readFromStream(" << GetName() << "): >> " << message << endl ;
	continue ;
      } 
      
      // Process abort statements
      if (!token.CompareTo("abort")) {
	TString message = parser.readLine() ;
	cout << "RooArgSet::readFromStream(" << GetName() << "): USER ABORT" << endl ;
	return kTRUE ;
      } 
      
      // Interpret the rest as <arg> = <value_expr> 
      RooAbsArg *arg ;

      if ((arg = find(token)) && !arg->getAttribute("Dynamic")) {
	if (parser.expectToken("=",kTRUE)) {
	  parser.zapToEnd(kTRUE) ;
	  retVal=kTRUE ;
	  cout << "RooArgSet::readFromStream(" << GetName() 
	       << "): missing '=' sign: " << arg << endl ;
	  continue ;
	}
	Bool_t argRet = arg->readFromStream(is,kFALSE,verbose) ;	
	if (!argRet && flagReadAtt) arg->setAttribute(flagReadAtt,kTRUE) ;
	retVal |= argRet ;
      } else {
	if (verbose) {
	  cout << "RooArgSet::readFromStream(" << GetName() << "): argument " 
	       << token << " not in list, ignored" << endl ;
	}
	parser.zapToEnd(kTRUE) ;
      }
    } else {
      parser.readLine() ;
    }
  }
  
  // Did we fully unwind the conditional stack?
  if (condStackLevel!=0) {
    cout << "RooArgSet::readFromStream(" << GetName() << "): missing 'endif'" << endl ;
    return kTRUE ;
  }
  
  return retVal ;
}





ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.