/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id: RooSuperCategory.cc,v 1.26 2005/06/23 15:08:57 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 [CAT] --
// RooSuperCategory consolidates several RooAbsCategoryLValue objects into
// a single category. The states of the super category consist of all the permutations
// of the input categories. The super category is an lvalue itself and a modification
// of its state will back propagate into a modification of its input categories.
//
// RooSuperCategory state are automatically defined and updated whenever an input
// category modifies its list of states

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <stdlib.h>
#include <stdio.h>
#include "TString.h"
#include "RooSuperCategory.h"
#include "RooStreamParser.h"
#include "RooArgSet.h"
#include "RooMultiCatIter.h"
#include "RooAbsCategoryLValue.h"

ClassImp(RooSuperCategory)
;

 RooSuperCategory::RooSuperCategory(const char *name, const char *title, const RooArgSet& inputCatList) :
  RooAbsCategoryLValue(name, title), _catSet("catSet","Input category set",this,kTRUE,kTRUE)
{  
  // Constructor from list of input categories

  // Copy category list
  TIterator* iter = inputCatList.createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*)iter->Next())) {
    if (!arg->IsA()->InheritsFrom(RooAbsCategoryLValue::Class())) {
      cout << "RooSuperCategory::RooSuperCategory(" << GetName() << "): input category " << arg->GetName() 
	   << " is not an lvalue" << endl ;
    }
    _catSet.add(*arg) ;
  }
  delete iter ;
  _catIter = _catSet.createIterator() ;
  
  updateIndexList() ;
}


 RooSuperCategory::RooSuperCategory(const RooSuperCategory& other, const char *name) :
  RooAbsCategoryLValue(other,name), _catSet("catSet",this,other._catSet)
{
  // Copy constructor
  _catIter = _catSet.createIterator() ;
  updateIndexList() ;
  setIndex(other.getIndex()) ;
}



 RooSuperCategory::~RooSuperCategory() 
{
  // Destructor
  delete _catIter ;
}



 TIterator* RooSuperCategory::MakeIterator() const 
{
  // Make an iterator over all state permutations of 
  // the input categories of this supercategory
  return new RooMultiCatIter(_catSet) ;
}



 void RooSuperCategory::updateIndexList()
{
  // Update the list of super-category states 
  clearTypes() ;
//   RooArgSet* catListClone = (RooArgSet*) _catSet.snapshot(kTRUE) ;

  RooMultiCatIter mcIter(_catSet) ;
  TObjString* obj ;
  Int_t i(0) ;
  while((obj = (TObjString*) mcIter.Next())) {
    // Register composite label
    defineTypeUnchecked(obj->String(),i++) ;
  }
//   _catSet = *catListClone ;
//   delete catListClone ;

  // Renumbering will invalidate cache
  setValueDirty() ;
}


 TString RooSuperCategory::currentLabel() const
{
  // Return the name of the current state, 
  // constructed from the state names of the input categories

  _catIter->Reset() ;

  // Construct composite label name
  TString label ;
  RooAbsCategory* cat ;
  Bool_t first(kTRUE) ;
  while((cat=(RooAbsCategory*) _catIter->Next())) {
    label.Append(first?"{":";") ;
    label.Append(cat->getLabel()) ;      
    first=kFALSE ;
  }
  label.Append("}") ;  

  return label ;
}


RooCatType
 RooSuperCategory::evaluate() const
{
  // Calculate the current value 
  if (isShapeDirty()) {
    const_cast<RooSuperCategory*>(this)->updateIndexList() ;
  }
  const RooCatType* ret = lookupType(currentLabel(),kTRUE) ;
  if (!ret) {
    cout << "RooSuperCat::evaluate(" << this << ") error: current state not defined: '" << currentLabel() << "'" << endl ;
    Print("v") ;
  }
  return *ret ;
}


 Bool_t RooSuperCategory::setIndex(Int_t index, Bool_t /*printError*/) 
{
  // Set the value of the super category by specifying the state index code
  // Indirectly sets the values of the input categories
  const RooCatType* type = lookupType(index,kTRUE) ;
  if (!type) return kTRUE ;
  return setType(type) ;
}


 Bool_t RooSuperCategory::setLabel(const char* label, Bool_t /*printError*/) 
{
  // Set the value of the super category by specifying the state name
  // Indirectly sets the values of the input categories
  const RooCatType* type = lookupType(label,kTRUE) ;
  if (!type) return kTRUE ;
  return setType(type) ;
}


 Bool_t RooSuperCategory::setType(const RooCatType* type, Bool_t /*printError*/)
{
  // Set the value of the super category by specifying the state object
  // Indirectly sets the values of the input categories

  char buf[1024] ;
  strcpy(buf,type->GetName()) ;

  RooAbsCategoryLValue* arg ;
  Bool_t error(kFALSE) ;

  // Parse composite label and set label of components to their values  
  char* ptr=buf+1 ;
  char* token = ptr ;
  _catIter->Reset() ;
  while ((arg=(RooAbsCategoryLValue*)_catIter->Next())) {

    // Delimit name token for this category
    if (*ptr=='{') {
      // Token is composite itself, terminate at matching '}'
      Int_t nBrak(1) ;
      while(*(++ptr)) {
	if (nBrak==0) {
	  *ptr = 0 ;
	  break ;
	}
	if (*ptr=='{') {
	  nBrak++ ;
	} else if (*ptr=='}') {
	  nBrak-- ;
	}
      }	
    } else {
      // Simple token, terminate at next semi-colon
      ptr = strtok(ptr,";}") ;
      ptr += strlen(ptr) ;
    }

    error |= arg->setLabel(token) ;
    token = ++ptr ;
  }
  
  return error ;
}



 void RooSuperCategory::printToStream(ostream& os, PrintOption opt, TString indent) const
{
  // Print the state of this object to the specified output stream.

  RooAbsCategory::printToStream(os,opt,indent) ;
  
  if (opt>=Verbose) {     
    os << indent << "--- RooSuperCategory ---" << endl;
    os << indent << "  Input category list:" << endl ;
    TString moreIndent(indent) ;
    moreIndent.Append("   ") ;
    _catSet.printToStream(os,Standard,moreIndent.Data()) ;
  }
}


 Bool_t RooSuperCategory::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/) 
{
  // Read object contents from given stream
  return kTRUE ;
}



 void RooSuperCategory::writeToStream(ostream& os, Bool_t compact) const
{
  // Write object contents to given stream
  RooAbsCategory::writeToStream(os,compact) ;
}



 Bool_t RooSuperCategory::inRange(const char* rangeName) const 
{
  // Return true of all of the input category states are in the given range

  _catIter->Reset() ;
  RooAbsCategoryLValue* cat ;
  while((cat = (RooAbsCategoryLValue*)_catIter->Next())) {
    if (!cat->inRange(rangeName)) {
      return kFALSE ;
    }
  }
  return kTRUE ;
}


 Bool_t RooSuperCategory::hasRange(const char* rangeName) const 
{
  _catIter->Reset() ;
  RooAbsCategoryLValue* cat ;
  while((cat = (RooAbsCategoryLValue*)_catIter->Next())) {
    if (cat->hasRange(rangeName)) return kTRUE ;
  }

  return kFALSE ;
}


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.