// RooChangeTracker is a meta object that tracks value
// changes in a given set of RooAbsArgs by registering itself as value
// client of these objects. The change tracker can perform an
// additional validation step where it also compares the numeric
// values of the tracked arguments with reference values to ensure
// that values have actually changed. This may be useful in case some
// of the tracked observables are in binned datasets where each
// observable propates a valueDirty flag when an event is loaded even
// though usually only one observable actually changes.
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include <math.h>
#include "RooChangeTracker.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooArgSet.h"
#include "RooMsgService.h"
using namespace std ;
ClassImp(RooChangeTracker)
;
RooChangeTracker::RooChangeTracker()
{
_realSetIter = _realSet.createIterator() ;
_catSetIter = _catSet.createIterator() ;
}
RooChangeTracker::RooChangeTracker(const char* name, const char* title, const RooArgSet& trackSet, Bool_t checkValues) :
RooAbsReal(name, title),
_realSet("realSet","Set of real-valued components to be tracked",this),
_catSet("catSet","Set of discrete-valued components to be tracked",this),
_realRef(trackSet.getSize()),
_catRef(trackSet.getSize()),
_checkVal(checkValues)
{
_realSetIter = _realSet.createIterator() ;
_catSetIter = _catSet.createIterator() ;
TIterator* iter = trackSet.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsReal*>(arg)) {
_realSet.add(*arg) ;
}
if (dynamic_cast<RooAbsCategory*>(arg)) {
_catSet.add(*arg) ;
}
}
delete iter ;
if (_checkVal) {
RooAbsReal* real ;
RooAbsCategory* cat ;
Int_t i(0) ;
while((real=(RooAbsReal*)_realSetIter->Next())) {
_realRef[i++] = real->getVal() ;
}
i=0 ;
while((cat=(RooAbsCategory*)_catSetIter->Next())) {
_catRef[i++] = cat->getIndex() ;
}
}
}
RooChangeTracker::RooChangeTracker(const RooChangeTracker& other, const char* name) :
RooAbsReal(other, name),
_realSet("realSet",this,other._realSet),
_catSet("catSet",this,other._catSet),
_realRef(other._realRef),
_catRef(other._catRef),
_checkVal(other._checkVal)
{
_realSetIter = _realSet.createIterator() ;
_catSetIter = _catSet.createIterator() ;
_realSet.add(other._realSet) ;
_catSet.add(other._catSet) ;
}
Bool_t RooChangeTracker::hasChanged(Bool_t clearState)
{
if (!isValueDirty()) {
return kFALSE ;
}
if (!_checkVal) {
if (clearState) {
clearValueDirty() ;
}
return kTRUE ;
}
_realSetIter->Reset() ;
_catSetIter->Reset() ;
RooAbsReal* real ;
RooAbsCategory* cat ;
Int_t i(0) ;
if (clearState) {
Bool_t valuesChanged(kFALSE) ;
while ((real=(RooAbsReal*)_realSetIter->Next())) {
if (real->getVal() != _realRef[i++]) {
valuesChanged = kTRUE ;
_realRef[i-1] = real->getVal() ;
}
}
i=0 ;
while ((cat=(RooAbsCategory*)_catSetIter->Next())) {
if (cat->getIndex() != _catRef[i++]) {
valuesChanged = kTRUE ;
_catRef[i-1] = cat->getIndex() ;
}
}
clearValueDirty() ;
return valuesChanged ;
} else {
while ((real=(RooAbsReal*)_realSetIter->Next())) {
if (real->getVal() != _realRef[i++]) {
return kTRUE ;
}
}
i=0 ;
while ((cat=(RooAbsCategory*)_catSetIter->Next())) {
if (cat->getIndex() != _catRef[i++]) {
return kTRUE ;
}
}
}
return kFALSE ;
}
RooChangeTracker::~RooChangeTracker()
{
if (_realSetIter) delete _realSetIter ;
if (_catSetIter) delete _catSetIter ;
}
RooArgSet RooChangeTracker::parameters() const
{
RooArgSet ret ;
ret.add(_realSet) ;
ret.add(_catSet) ;
return ret ;
}