/*****************************************************************************
* Project: RooFit *
* Package: RooFitCore *
* @(#)root/roofitcore:$Id$
* 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) *
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// RooRandomizeParamMCSModule is an add-on modules to RooMCStudy that
// allows you to randomize input generation parameters. Randomized generation
// parameters can be sampled from a uniform or Gaussian distribution.
// For every randomized parameter, an extra variable is added to
// RooMCStudy::fitParDataSet() named _gen that indicates the actual
// value used for generation for each trial.
//
// You can also choose to randomize the sum of N parameters, rather
// than a single parameter. In that case common multiplicative scale
// factor is applied to each component to bring the sum to the desired
// target value taken from either uniform or Gaussian sampling. This
// latter option is for example useful if you want to change the total
// number of expected events of an extended p.d.f
// END_HTML
//
#include "Riostream.h"
#include "RooDataSet.h"
#include "RooRealVar.h"
#include "RooRandom.h"
#include "TString.h"
#include "RooFit.h"
#include "RooFitResult.h"
#include "RooAddition.h"
#include "RooMsgService.h"
#include "RooRandomizeParamMCSModule.h"
using namespace std ;
ClassImp(RooRandomizeParamMCSModule)
;
////////////////////////////////////////////////////////////////////////////////
/// Constructor
RooRandomizeParamMCSModule::RooRandomizeParamMCSModule() :
RooAbsMCStudyModule("RooRandomizeParamMCSModule","RooRandomizeParamMCSModule"), _data(0)
{
}
////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
RooRandomizeParamMCSModule::RooRandomizeParamMCSModule(const RooRandomizeParamMCSModule& other) :
RooAbsMCStudyModule(other),
_unifParams(other._unifParams),
_gausParams(other._gausParams),
_data(0)
{
}
////////////////////////////////////////////////////////////////////////////////
/// Destructor
RooRandomizeParamMCSModule:: ~RooRandomizeParamMCSModule()
{
if (_data) {
delete _data ;
}
}
////////////////////////////////////////////////////////////////////////////////
/// Request uniform smearing of param in range [lo,hi] in RooMCStudy
/// generation cycle
void RooRandomizeParamMCSModule::sampleUniform(RooRealVar& param, Double_t lo, Double_t hi)
{
// If we're already attached to a RooMCStudy, check that given param is actual generator model parameter
// If not attached, this check is repeated at the attachment moment
if (genParams()) {
RooRealVar* actualPar = static_cast(genParams()->find(param.GetName())) ;
if (!actualPar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << param.GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
return ;
}
}
_unifParams.push_back(UniParam(¶m,lo,hi)) ;
}
////////////////////////////////////////////////////////////////////////////////
/// Request Gaussian smearing of param in with mean 'mean' and width
/// 'sigma' in RooMCStudy generation cycle
void RooRandomizeParamMCSModule::sampleGaussian(RooRealVar& param, Double_t mean, Double_t sigma)
{
// If we're already attached to a RooMCStudy, check that given param is actual generator model parameter
// If not attached, this check is repeated at the attachment moment
if (genParams()) {
RooRealVar* actualPar = static_cast(genParams()->find(param.GetName())) ;
if (!actualPar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << param.GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
return ;
}
}
_gausParams.push_back(GausParam(¶m,mean,sigma)) ;
}
////////////////////////////////////////////////////////////////////////////////
/// Request uniform smearing of sum of parameters in paramSet uniform
/// smearing in range [lo,hi] in RooMCStudy generation cycle. This
/// option applies a common multiplicative factor to each parameter
/// in paramSet to make the sum of the parameters add up to the
/// sampled value in the range [lo,hi]
void RooRandomizeParamMCSModule::sampleSumUniform(const RooArgSet& paramSet, Double_t lo, Double_t hi)
{
// Check that all args are RooRealVars
RooArgSet okset ;
TIterator* iter = paramSet.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
// Check that arg is a RooRealVar
RooRealVar* rrv = dynamic_cast(arg) ;
if (!rrv) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::sampleSumUniform() ERROR: input parameter " << arg->GetName() << " is not a RooRealVar and is ignored" << endl ;
continue;
}
okset.add(*rrv) ;
}
delete iter ;
// If we're already attached to a RooMCStudy, check that given param is actual generator model parameter
// If not attached, this check is repeated at the attachment moment
RooArgSet okset2 ;
if (genParams()) {
TIterator* psiter = okset.createIterator() ;
RooAbsArg* arg2 ;
while ((arg2=(RooAbsArg*)psiter->Next())) {
RooRealVar* actualVar= static_cast(genParams()->find(arg2->GetName())) ;
if (!actualVar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::sampleSumUniform: variable " << arg2->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
} else {
okset2.add(*actualVar) ;
}
}
delete psiter ;
} else {
// If genParams() are not available, skip this check for now
okset2.add(okset) ;
}
_unifParamSets.push_back(UniParamSet(okset2,lo,hi)) ;
}
////////////////////////////////////////////////////////////////////////////////
/// Request gaussian smearing of sum of parameters in paramSet
/// uniform smearing with mean 'mean' and width 'sigma' in RooMCStudy
/// generation cycle. This option applies a common multiplicative
/// factor to each parameter in paramSet to make the sum of the
/// parameters add up to the sampled value from the
/// gaussian(mean,sigma)
void RooRandomizeParamMCSModule::sampleSumGauss(const RooArgSet& paramSet, Double_t mean, Double_t sigma)
{
// Check that all args are RooRealVars
RooArgSet okset ;
TIterator* iter = paramSet.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
// Check that arg is a RooRealVar
RooRealVar* rrv = dynamic_cast(arg) ;
if (!rrv) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::sampleSumGauss() ERROR: input parameter " << arg->GetName() << " is not a RooRealVar and is ignored" << endl ;
continue;
}
okset.add(*rrv) ;
}
// If we're already attached to a RooMCStudy, check that given param is actual generator model parameter
// If not attached, this check is repeated at the attachment moment
RooArgSet okset2 ;
if (genParams()) {
TIterator* psiter = okset.createIterator() ;
RooAbsArg* arg2 ;
while ((arg2=(RooAbsArg*)psiter->Next())) {
RooRealVar* actualVar= static_cast(genParams()->find(arg2->GetName())) ;
if (!actualVar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::sampleSumUniform: variable " << arg2->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
} else {
okset2.add(*actualVar) ;
}
}
delete psiter ;
} else {
// If genParams() are not available, skip this check for now
okset2.add(okset) ;
}
_gausParamSets.push_back(GausParamSet(okset,mean,sigma)) ;
}
////////////////////////////////////////////////////////////////////////////////
/// Initialize module after attachment to RooMCStudy object
Bool_t RooRandomizeParamMCSModule::initializeInstance()
{
// Loop over all uniform smearing parameters
std::list::iterator uiter ;
for (uiter= _unifParams.begin() ; uiter!= _unifParams.end() ; ++uiter) {
// Check that listed variable is actual generator model parameter
RooRealVar* actualPar = static_cast(genParams()->find(uiter->_param->GetName())) ;
if (!actualPar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << uiter->_param->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
uiter = _unifParams.erase(uiter) ;
continue ;
}
uiter->_param = actualPar ;
// Add variable to summary dataset to hold generator value
TString parName = Form("%s_gen",uiter->_param->GetName()) ;
TString parTitle = Form("%s as generated",uiter->_param->GetTitle()) ;
RooRealVar* par_gen = new RooRealVar(parName.Data(),parTitle.Data(),0) ;
_genParSet.addOwned(*par_gen) ;
}
// Loop over all gaussian smearing parameters
std::list::iterator giter ;
for (giter= _unifParams.begin() ; giter!= _unifParams.end() ; ++giter) {
// Check that listed variable is actual generator model parameter
RooRealVar* actualPar = static_cast(genParams()->find(giter->_param->GetName())) ;
if (!actualPar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << giter->_param->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
giter = _unifParams.erase(giter) ;
continue ;
}
giter->_param = actualPar ;
// Add variable to summary dataset to hold generator value
TString parName = Form("%s_gen",giter->_param->GetName()) ;
TString parTitle = Form("%s as generated",giter->_param->GetTitle()) ;
RooRealVar* par_gen = new RooRealVar(parName.Data(),parTitle.Data(),0) ;
_genParSet.addOwned(*par_gen) ;
}
// Loop over all uniform smearing set of parameters
std::list::iterator usiter ;
for (usiter= _unifParamSets.begin() ; usiter!= _unifParamSets.end() ; ++usiter) {
// Check that all listed variables are actual generator model parameters
RooArgSet actualPSet ;
TIterator* psiter = usiter->_pset.createIterator() ;
RooAbsArg* arg ;
while ((arg=(RooAbsArg*)psiter->Next())) {
RooRealVar* actualVar= static_cast(genParams()->find(arg->GetName())) ;
if (!actualVar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << arg->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
} else {
actualPSet.add(*actualVar) ;
}
}
delete psiter ;
usiter->_pset.removeAll() ;
usiter->_pset.add(actualPSet) ;
// Add variables to summary dataset to hold generator values
TIterator* iter = usiter->_pset.createIterator() ;
RooRealVar* param ;
while((param=(RooRealVar*)iter->Next())) {
TString parName = Form("%s_gen",param->GetName()) ;
TString parTitle = Form("%s as generated",param->GetTitle()) ;
RooRealVar* par_gen = new RooRealVar(parName.Data(),parTitle.Data(),0) ;
_genParSet.addOwned(*par_gen) ;
}
delete iter ;
}
// Loop over all gaussian smearing set of parameters
std::list::iterator ugiter ;
for (ugiter= _gausParamSets.begin() ; ugiter!= _gausParamSets.end() ; ++ugiter) {
// Check that all listed variables are actual generator model parameters
RooArgSet actualPSet ;
TIterator* psiter = ugiter->_pset.createIterator() ;
RooAbsArg* arg ;
while ((arg=(RooAbsArg*)psiter->Next())) {
RooRealVar* actualVar= static_cast(genParams()->find(arg->GetName())) ;
if (!actualVar) {
oocoutW((TObject*)0,InputArguments) << "RooRandomizeParamMCSModule::initializeInstance: variable " << arg->GetName() << " is not a parameter of RooMCStudy model and is ignored!" << endl ;
} else {
actualPSet.add(*actualVar) ;
}
}
ugiter->_pset.removeAll() ;
ugiter->_pset.add(actualPSet) ;
// Add variables to summary dataset to hold generator values
TIterator* iter = ugiter->_pset.createIterator() ;
RooRealVar* param ;
while((param=(RooRealVar*)iter->Next())) {
TString parName = Form("%s_gen",param->GetName()) ;
TString parTitle = Form("%s as generated",param->GetTitle()) ;
RooRealVar* par_gen = new RooRealVar(parName.Data(),parTitle.Data(),0) ;
_genParSet.addOwned(*par_gen) ;
}
}
// Create new dataset to be merged with RooMCStudy::fitParDataSet
_data = new RooDataSet("DeltaLLSigData","Additional data for Delta(-log(L)) study",_genParSet) ;
return kTRUE ;
}
////////////////////////////////////////////////////////////////////////////////
/// Initialize module at beginning of RooCMStudy run
Bool_t RooRandomizeParamMCSModule::initializeRun(Int_t /*numSamples*/)
{
// Clear dataset at beginning of run
_data->reset() ;
return kTRUE ;
}
////////////////////////////////////////////////////////////////////////////////
/// Apply all smearings to generator parameters
Bool_t RooRandomizeParamMCSModule::processBeforeGen(Int_t /*sampleNum*/)
{
// Apply uniform smearing to all generator parameters for which it is requested
std::list::iterator uiter ;
for (uiter= _unifParams.begin() ; uiter!= _unifParams.end() ; ++uiter) {
Double_t newVal = RooRandom::randomGenerator()->Uniform(uiter->_lo,uiter->_hi) ;
oocoutE((TObject*)0,Generation) << "RooRandomizeParamMCSModule::processBeforeGen: applying uniform smearing to generator parameter "
<< uiter->_param->GetName() << " in range [" << uiter->_lo << "," << uiter->_hi << "], chosen value for this sample is " << newVal << endl ;
uiter->_param->setVal(newVal) ;
RooRealVar* genpar = static_cast(_genParSet.find(Form("%s_gen",uiter->_param->GetName()))) ;
genpar->setVal(newVal) ;
}
// Apply gaussian smearing to all generator parameters for which it is requested
std::list::iterator giter ;
for (giter= _gausParams.begin() ; giter!= _gausParams.end() ; ++giter) {
Double_t newVal = RooRandom::randomGenerator()->Gaus(giter->_mean,giter->_sigma) ;
oocoutI((TObject*)0,Generation) << "RooRandomizeParamMCSModule::processBeforeGen: applying gaussian smearing to generator parameter "
<< giter->_param->GetName() << " with a mean of " << giter->_mean << " and a width of " << giter->_sigma << ", chosen value for this sample is " << newVal << endl ;
giter->_param->setVal(newVal) ;
RooRealVar* genpar = static_cast(_genParSet.find(Form("%s_gen",giter->_param->GetName()))) ;
genpar->setVal(newVal) ;
}
// Apply uniform smearing to all sets of generator parameters for which it is requested
std::list::iterator usiter ;
for (usiter= _unifParamSets.begin() ; usiter!= _unifParamSets.end() ; ++usiter) {
// Calculate new value for sum
Double_t newVal = RooRandom::randomGenerator()->Uniform(usiter->_lo,usiter->_hi) ;
oocoutI((TObject*)0,Generation) << "RooRandomizeParamMCSModule::processBeforeGen: applying uniform smearing to sum of set of generator parameters "
<< usiter->_pset
<< " in range [" << usiter->_lo << "," << usiter->_hi << "], chosen sum value for this sample is " << newVal << endl ;
// Determine original value of sum and calculate per-component scale factor to obtain new valye for sum
RooAddition sumVal("sumVal","sumVal",usiter->_pset) ;
Double_t compScaleFactor = newVal/sumVal.getVal() ;
// Apply multiplicative correction to each term of the sum
TIterator* iter = usiter->_pset.createIterator() ;
RooRealVar* param ;
while((param=(RooRealVar*)iter->Next())) {
param->setVal(param->getVal()*compScaleFactor) ;
RooRealVar* genpar = static_cast(_genParSet.find(Form("%s_gen",param->GetName()))) ;
genpar->setVal(param->getVal()) ;
}
delete iter ;
}
// Apply gaussian smearing to all sets of generator parameters for which it is requested
std::list::iterator gsiter ;
for (gsiter= _gausParamSets.begin() ; gsiter!= _gausParamSets.end() ; ++gsiter) {
// Calculate new value for sum
Double_t newVal = RooRandom::randomGenerator()->Gaus(gsiter->_mean,gsiter->_sigma) ;
oocoutI((TObject*)0,Generation) << "RooRandomizeParamMCSModule::processBeforeGen: applying gaussian smearing to sum of set of generator parameters "
<< gsiter->_pset
<< " with a mean of " << gsiter->_mean << " and a width of " << gsiter->_sigma
<< ", chosen value for this sample is " << newVal << endl ;
// Determine original value of sum and calculate per-component scale factor to obtain new valye for sum
RooAddition sumVal("sumVal","sumVal",gsiter->_pset) ;
Double_t compScaleFactor = newVal/sumVal.getVal() ;
// Apply multiplicative correction to each term of the sum
TIterator* iter = gsiter->_pset.createIterator() ;
RooRealVar* param ;
while((param=(RooRealVar*)iter->Next())) {
param->setVal(param->getVal()*compScaleFactor) ;
RooRealVar* genpar = static_cast(_genParSet.find(Form("%s_gen",param->GetName()))) ;
genpar->setVal(param->getVal()) ;
}
}
// Store generator values for all modified parameters
_data->add(_genParSet) ;
return kTRUE ;
}
////////////////////////////////////////////////////////////////////////////////
/// Return auxiliary data of this module so that it is merged with
/// RooMCStudy::fitParDataSet()
RooDataSet* RooRandomizeParamMCSModule::finalizeRun()
{
return _data ;
}