// @(#)root/roostats:$Id: cranmer $ // Author: Kyle Cranmer, Akira Shibata // Author: Giovanni Petrucciani (UCSD) (log-interpolation) /************************************************************************* * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //_________________________________________________ /* BEGIN_HTML

END_HTML */ // #include "RooFit.h" #include "Riostream.h" #include #include "TMath.h" #include "RooAbsReal.h" #include "RooRealVar.h" #include "RooArgList.h" #include "RooMsgService.h" #include "TMath.h" #include "RooStats/HistFactory/FlexibleInterpVar.h" using namespace std; ClassImp(RooStats::HistFactory::FlexibleInterpVar) using namespace RooStats; using namespace HistFactory; //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar() { // Default constructor _paramIter = _paramList.createIterator() ; _nominal = 0; _interpBoundary=1.; _logInit = kFALSE ; } //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar(const char* name, const char* title, const RooArgList& paramList, Double_t nominal, vector low, vector high) : RooAbsReal(name, title), _paramList("paramList","List of paramficients",this), _nominal(nominal), _low(low), _high(high), _interpBoundary(1.) { _logInit = kFALSE ; _paramIter = _paramList.createIterator() ; TIterator* paramIter = paramList.createIterator() ; RooAbsArg* param ; while((param = (RooAbsArg*)paramIter->Next())) { if (!dynamic_cast(param)) { coutE(InputArguments) << "FlexibleInterpVar::ctor(" << GetName() << ") ERROR: paramficient " << param->GetName() << " is not of type RooAbsReal" << endl ; assert(0) ; } _paramList.add(*param) ; _interpCode.push_back(0); // default code } delete paramIter ; } //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar(const char* name, const char* title, const RooArgList& paramList, double nominal, const RooArgList& low, const RooArgList& high) : RooAbsReal(name, title), _paramList("paramList","List of paramficients",this), _nominal(nominal), _interpBoundary(1.) { RooFIter lowIter = low.fwdIterator() ; RooAbsReal* val ; while ((val = (RooAbsReal*) lowIter.next())) { _low.push_back(val->getVal()) ; } RooFIter highIter = high.fwdIterator() ; while ((val = (RooAbsReal*) highIter.next())) { _high.push_back(val->getVal()) ; } _logInit = kFALSE ; _paramIter = _paramList.createIterator() ; TIterator* paramIter = paramList.createIterator() ; RooAbsArg* param ; while((param = (RooAbsArg*)paramIter->Next())) { if (!dynamic_cast(param)) { coutE(InputArguments) << "FlexibleInterpVar::ctor(" << GetName() << ") ERROR: paramficient " << param->GetName() << " is not of type RooAbsReal" << endl ; assert(0) ; } _paramList.add(*param) ; _interpCode.push_back(0); // default code } delete paramIter ; } //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar(const char* name, const char* title, const RooArgList& paramList, double nominal, vector low, vector high, vector code) : RooAbsReal(name, title), _paramList("paramList","List of paramficients",this), _nominal(nominal), _low(low), _high(high), _interpCode(code), _interpBoundary(1.) { _logInit = kFALSE ; _paramIter = _paramList.createIterator() ; TIterator* paramIter = paramList.createIterator() ; RooAbsArg* param ; while((param = (RooAbsArg*)paramIter->Next())) { if (!dynamic_cast(param)) { coutE(InputArguments) << "FlexibleInterpVar::ctor(" << GetName() << ") ERROR: paramficient " << param->GetName() << " is not of type RooAbsReal" << endl ; assert(0) ; } _paramList.add(*param) ; } delete paramIter ; } //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar(const char* name, const char* title) : RooAbsReal(name, title), _paramList("paramList","List of coefficients",this) { // Constructor of flat polynomial function _logInit = kFALSE ; _paramIter = _paramList.createIterator() ; } //_____________________________________________________________________________ FlexibleInterpVar::FlexibleInterpVar(const FlexibleInterpVar& other, const char* name) : RooAbsReal(other, name), _paramList("paramList",this,other._paramList), _nominal(other._nominal), _low(other._low), _high(other._high), _interpCode(other._interpCode), _interpBoundary(other._interpBoundary) { // Copy constructor _logInit = kFALSE ; _paramIter = _paramList.createIterator() ; } //_____________________________________________________________________________ FlexibleInterpVar::~FlexibleInterpVar() { // Destructor delete _paramIter ; } //_____________________________________________________________________________ void FlexibleInterpVar::setInterpCode(RooAbsReal& param, int code){ int index = _paramList.index(¶m); if(index<0){ coutE(InputArguments) << "FlexibleInterpVar::setInterpCode ERROR: " << param.GetName() << " is not in list" << endl ; } else { coutW(InputArguments) << "FlexibleInterpVar::setInterpCode : " << param.GetName() << " is now " << code << endl ; _interpCode.at(index) = code; } // GHL: Adding suggestion by Swagato: setValueDirty(); } //_____________________________________________________________________________ void FlexibleInterpVar::setAllInterpCodes(int code){ for(unsigned int i=0; i<_interpCode.size(); ++i){ _interpCode.at(i) = code; } // GHL: Adding suggestion by Swagato: setValueDirty(); } //_____________________________________________________________________________ void FlexibleInterpVar::setNominal(Double_t newNominal){ coutW(InputArguments) << "FlexibleInterpVar::setNominal : nominal is now " << newNominal << endl ; _nominal = newNominal; setValueDirty(); } //_____________________________________________________________________________ void FlexibleInterpVar::setLow(RooAbsReal& param, Double_t newLow){ int index = _paramList.index(¶m); if(index<0){ coutE(InputArguments) << "FlexibleInterpVar::setLow ERROR: " << param.GetName() << " is not in list" << endl ; } else { coutW(InputArguments) << "FlexibleInterpVar::setLow : " << param.GetName() << " is now " << newLow << endl ; _low.at(index) = newLow; } setValueDirty(); } //_____________________________________________________________________________ void FlexibleInterpVar::setHigh(RooAbsReal& param, Double_t newHigh){ int index = _paramList.index(¶m); if(index<0){ coutE(InputArguments) << "FlexibleInterpVar::setHigh ERROR: " << param.GetName() << " is not in list" << endl ; } else { coutW(InputArguments) << "FlexibleInterpVar::setHigh : " << param.GetName() << " is now " << newHigh << endl ; _high.at(index) = newHigh; } setValueDirty(); } //_____________________________________________________________________________ void FlexibleInterpVar::printAllInterpCodes(){ for(unsigned int i=0; i<_interpCode.size(); ++i){ coutI(InputArguments) <<"interp code for " << _paramList.at(i)->GetName() << " = " << _interpCode.at(i) <GetName() << ": low value = " << _low.at(i) << endl; if( _high.at(i) <= 0.001 ) coutE(InputArguments) << GetName() << ", " << _paramList.at(i)->GetName() << ": high value = " << _high.at(i) << endl; } } //_____________________________________________________________________________ Double_t FlexibleInterpVar::evaluate() const { // Calculate and return value of polynomial Double_t total(_nominal) ; _paramIter->Reset() ; RooAbsReal* param ; //const RooArgSet* nset = _paramList.nset() ; int i=0; while((param=(RooAbsReal*)_paramIter->Next())) { // param->Print("v"); Int_t icode = _interpCode[i] ; switch(icode) { case 0: { // piece-wise linear if(param->getVal()>0) total += param->getVal()*(_high[i] - _nominal ); else total += param->getVal()*(_nominal - _low[i]); break ; } case 1: { // pice-wise log if(param->getVal()>=0) total *= pow(_high[i]/_nominal, +param->getVal()); else total *= pow(_low[i]/_nominal, -param->getVal()); break ; } case 2: { // parabolic with linear double a = 0.5*(_high[i]+_low[i])-_nominal; double b = 0.5*(_high[i]-_low[i]); double c = 0; if(param->getVal()>1 ){ total += (2*a+b)*(param->getVal()-1)+_high[i]-_nominal; } else if(param->getVal()<-1 ) { total += -1*(2*a-b)*(param->getVal()+1)+_low[i]-_nominal; } else { total += a*pow(param->getVal(),2) + b*param->getVal()+c; } break ; } case 3: { //parabolic version of log-normal double a = 0.5*(_high[i]+_low[i])-_nominal; double b = 0.5*(_high[i]-_low[i]); double c = 0; if(param->getVal()>1 ){ total += (2*a+b)*(param->getVal()-1)+_high[i]-_nominal; } else if(param->getVal()<-1 ) { total += -1*(2*a-b)*(param->getVal()+1)+_low[i]-_nominal; } else { total += a*pow(param->getVal(),2) + b*param->getVal()+c; } break ; } case 4: { double boundary = _interpBoundary; // piece-wise log + parabolic if(param->getVal()>=boundary) { total *= pow(_high[i]/_nominal, +param->getVal()); } else if (param->getVal() < boundary && param->getVal() > -boundary && boundary != 0) { double x0 = boundary; double x = param->getVal(); if (!_logInit) { _logInit=kTRUE ; _logHi.resize(_high.size()) ; for (unsigned int j=0 ; j<_high.size() ; j++) { _logHi[j] = TMath::Log(_high.at(j)) ; } _logLo.resize(_low.size()) ; for (unsigned int j=0 ; j<_low.size() ; j++) { _logLo[j] = TMath::Log(_low.at(j)) ; } _powHi.resize(_high.size()) ; for (unsigned int j=0 ; j<_high.size() ; j++) { _powHi[j] = pow(_high.at(j)/_nominal, x0); } _powLo.resize(_low.size()) ; for (unsigned int j=0 ; j<_low.size() ; j++) { _powLo[j] = pow(_low.at(j)/_nominal, x0); } } // GHL: Swagato's suggestions // if( _low[i] == 0 ) _low[i] = 0.0001; // if( _high[i] == 0 ) _high[i] = 0.0001; // GHL: Swagato's suggestions double pow_up = _powHi[i] ; double pow_down = _powLo[i] ; double pow_up_log = _high[i] <= 0.0 ? 0.0 : pow_up*_logHi[i] ; double pow_down_log = _low[i] <= 0.0 ? 0.0 : -pow_down*_logLo[i] ; double pow_up_log2 = _high[i] <= 0.0 ? 0.0 : pow_up_log*_logHi[i] ; double pow_down_log2= _low[i] <= 0.0 ? 0.0 : -pow_down_log*_logLo[i] ; /* double pow_up = pow(_high[i]/_nominal, x0); double pow_down = pow(_low[i]/_nominal, x0); double pow_up_log = pow_up*TMath::Log(_high[i]); double pow_down_log = -pow_down*TMath::Log(_low[i]); double pow_up_log2 = pow_up_log*TMath::Log(_high[i]); double pow_down_log2= pow_down_log*TMath::Log(_low[i]); */ double S0 = (pow_up+pow_down)/2; double A0 = (pow_up-pow_down)/2; double S1 = (pow_up_log+pow_down_log)/2; double A1 = (pow_up_log-pow_down_log)/2; double S2 = (pow_up_log2+pow_down_log2)/2; double A2 = (pow_up_log2-pow_down_log2)/2; //fcns+der+2nd_der are eq at bd double a = 1./(8*pow(x0, 1))*( 15*A0 - 7*x0*S1 + x0*x0*A2); double b = 1./(8*pow(x0, 2))*(-24 + 24*S0 - 9*x0*A1 + x0*x0*S2); double c = 1./(4*pow(x0, 3))*( - 5*A0 + 5*x0*S1 - x0*x0*A2); double d = 1./(4*pow(x0, 4))*( 12 - 12*S0 + 7*x0*A1 - x0*x0*S2); double e = 1./(8*pow(x0, 5))*( + 3*A0 - 3*x0*S1 + x0*x0*A2); double f = 1./(8*pow(x0, 6))*( -8 + 8*S0 - 5*x0*A1 + x0*x0*S2); double xx = x*x ; double xxx = xx*x ; total *= 1 + a*x + b*xx + c*xxx + d*xx*xx + e*xxx*xx + f*xxx*xxx; } else if (param->getVal()<=-boundary) { total *= pow(_low[i]/_nominal, -param->getVal()); } break ; } default: { coutE(InputArguments) << "FlexibleInterpVar::evaluate ERROR: " << param->GetName() << " with unknown interpolation code" << endl ; } } ++i; } if(total<=0) { total=1E-9; } return total; } void FlexibleInterpVar::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const { RooAbsReal::printMultiline(os,contents,verbose,indent); os << indent << "--- FlexibleInterpVar ---" << endl; printFlexibleInterpVars(os); } void FlexibleInterpVar::printFlexibleInterpVars(ostream& os) const { _paramIter->Reset(); for (int i=0;i<(int)_low.size();i++) { RooAbsReal* param=(RooAbsReal*)_paramIter->Next(); os << setw(36) << param->GetName()<<": "<