59using std::endl, std::ostream;
105 const RooArgSet& projDeps, RooAbsTestStatistic::Configuration
const& cfg) :
107 _paramSet(
"paramSet",
"Set of parameters",this),
110 _projDeps(static_cast<
RooArgSet*>(projDeps.Clone())),
111 _rangeName(cfg.rangeName),
112 _addCoefRangeName(cfg.addCoefRangeName),
113 _splitRange(cfg.splitCutRange),
116 _gofOpMode{(cfg.nCPU>1 || cfg.nCPU==-1) ? MPMaster : (isSimultaneousFit(real,
data) ? SimMaster : Slave)},
117 _nEvents{
data.numEntries()},
118 _nCPU(cfg.nCPU != -1 ? cfg.nCPU : 1),
119 _mpinterl(cfg.interleave),
120 _takeGlobalObservablesFromData{cfg.takeGlobalObservablesFromData}
131RooAbsTestStatistic::RooAbsTestStatistic(
const RooAbsTestStatistic& other,
const char*
name) :
133 _paramSet(
"paramSet",
"Set of parameters",this),
136 _projDeps(static_cast<
RooArgSet*>(other._projDeps->Clone())),
137 _rangeName(other._rangeName),
138 _addCoefRangeName(other._addCoefRangeName),
139 _splitRange(other._splitRange),
140 _verbose(other._verbose),
142 _gofOpMode{(other._nCPU>1 || other._nCPU==-1) ? MPMaster
143 : (isSimultaneousFit(*other._func, *other._data) ? SimMaster : Slave)},
144 _nEvents{_data->numEntries()},
145 _nCPU(other._nCPU != -1 ? other._nCPU : 1),
146 _mpinterl(other._mpinterl),
147 _doOffset(other._doOffset),
148 _takeGlobalObservablesFromData{other._takeGlobalObservablesFromData},
149 _offset(other._offset),
150 _evalCarry(other._evalCarry)
153 _paramSet.add(other._paramSet) ;
161RooAbsTestStatistic::~RooAbsTestStatistic()
163 if (MPMaster == _gofOpMode && _init) {
164 for (
Int_t i = 0; i < _nCPU; ++i)
delete _mpfeArray[i];
165 delete[] _mpfeArray ;
180double RooAbsTestStatistic::evaluate()
const
184 const_cast<RooAbsTestStatistic*
>(
this)->
initialize() ;
187 if (SimMaster == _gofOpMode) {
192 ret = combinedValue(
reinterpret_cast<RooAbsReal**
>(
const_cast<std::unique_ptr<RooAbsTestStatistic>*
>(_gofArray.data())),_gofArray.size());
197 for (
auto& gof : _gofArray) {
199 double y = gof->getValV();
200 carry += gof->getCarry();
202 const double t =
sum +
y;
203 carry = (t -
sum) -
y;
214 const double norm = globalNormalization();
221 }
else if (MPMaster == _gofOpMode) {
224 for (
Int_t i = 0; i < _nCPU; ++i) _mpfeArray[i]->calculate();
228 for (
Int_t i = 0; i < _nCPU; ++i) {
229 double y = _mpfeArray[i]->getValV();
230 carry += _mpfeArray[i]->getCarry();
232 const double t =
sum +
y;
233 carry = (t -
sum) -
y;
240 const double norm = globalNormalization();
250 Int_t nLast(_nEvents);
255 nFirst = _nEvents * _setNum / _numSets ;
256 nLast = _nEvents * (_setNum+1) / _numSets ;
273 throw std::logic_error(
"this should never happen");
277 double ret = evaluatePartition(nFirst,nLast,nStep);
280 const double norm = globalNormalization();
297bool RooAbsTestStatistic::initialize()
299 if (_init)
return false;
301 if (MPMaster == _gofOpMode) {
302 initMPMode(_func,_data,_projDeps,_rangeName,_addCoefRangeName) ;
303 }
else if (SimMaster == _gofOpMode) {
304 initSimMode(
static_cast<RooSimultaneous*
>(_func),_data,_projDeps,_rangeName,_addCoefRangeName) ;
315bool RooAbsTestStatistic::redirectServersHook(
const RooAbsCollection& newServerList,
bool mustReplaceAll,
bool nameChange,
bool isRecursive)
317 if (SimMaster == _gofOpMode) {
319 for(
auto& gof : _gofArray) {
320 gof->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
322 }
else if (MPMaster == _gofOpMode&& _mpfeArray) {
324 for (
Int_t i = 0; i < _nCPU; ++i) {
326 _mpfeArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
340void RooAbsTestStatistic::printCompactTreeHook(ostream& os,
const char*
indent)
342 if (SimMaster == _gofOpMode) {
344 os <<
indent <<
"RooAbsTestStatistic begin GOF contents" << std::endl ;
345 for (std::size_t i = 0; i < _gofArray.size(); ++i) {
347 indent2 +=
"[" + std::to_string(i) +
"] ";
348 _gofArray[i]->printCompactTreeHook(os,indent2);
350 os <<
indent <<
"RooAbsTestStatistic end GOF contents" << std::endl;
351 }
else if (MPMaster == _gofOpMode) {
361void RooAbsTestStatistic::setMPSet(
Int_t inSetNum,
Int_t inNumSets)
363 _setNum = inSetNum; _numSets = inNumSets;
366 if (SimMaster == _gofOpMode) {
369 for(
auto& gof : _gofArray) {
370 gof->setMPSet(inSetNum,inNumSets);
381void RooAbsTestStatistic::initMPMode(
RooAbsReal* real,
RooAbsData*
data,
const RooArgSet* projDeps, std::string
const& rangeName, std::string
const& addCoefRangeName)
383 _mpfeArray =
new pRooRealMPFE[_nCPU];
387 cfg.rangeName = rangeName;
388 cfg.addCoefRangeName = addCoefRangeName;
390 cfg.interleave = _mpinterl;
391 cfg.verbose = _verbose;
392 cfg.splitCutRange = _splitRange;
393 cfg.takeGlobalObservablesFromData = _takeGlobalObservablesFromData;
397 if(
auto thisAsRooAbsOptTestStatistic =
dynamic_cast<RooAbsOptTestStatistic const*
>(
this)) {
398 cfg.integrateOverBinsPrecision = thisAsRooAbsOptTestStatistic->_integrateBinsPrecision;
400 RooAbsTestStatistic* gof = create(
GetName(),GetTitle(),*real,*
data,*projDeps,cfg);
401 gof->recursiveRedirectServers(_paramSet);
403 for (
Int_t i = 0; i < _nCPU; ++i) {
404 gof->setMPSet(i,_nCPU);
406 gof->SetTitle(
Form(
"%s_GOF%d",GetTitle(),i));
408 ccoutD(Eval) <<
"RooAbsTestStatistic::initMPMode: starting remote server process #" << i << std::endl;
409 _mpfeArray[i] =
new RooRealMPFE(
Form(
"%s_%zx_MPFE%d",
GetName(),
reinterpret_cast<size_t>(
this),i),
Form(
"%s_%zx_MPFE%d",GetTitle(),
reinterpret_cast<size_t>(
this),i),*gof,
false);
411 _mpfeArray[i]->initialize();
413 _mpfeArray[i]->followAsSlave(*_mpfeArray[0]);
416 _mpfeArray[_nCPU - 1]->addOwnedComponents(*gof);
417 coutI(Eval) <<
"RooAbsTestStatistic::initMPMode: started " << _nCPU <<
" remote server process." << std::endl;
432 std::string
const& rangeName, std::string
const& addCoefRangeName)
437 std::vector<std::unique_ptr<RooAbsData>> dsetList{
const_cast<RooAbsData*
>(
data)->split(*simpdf,processEmptyDataSets())};
440 for (
const auto& catState : simCat) {
441 const std::string& catName = catState.first;
446 if(!rangeName.empty()) {
449 auto simCatAsRooCategory =
dynamic_cast<RooCategory*
>(&simCat);
450 if(simCatAsRooCategory && !simCatAsRooCategory->isStateInRange(rangeName.c_str(), catIndex)) {
457 auto found = std::find_if(dsetList.begin(), dsetList.end(), [&](
auto const &item) {
458 return catName == item->GetName();
460 RooAbsData *dset = found != dsetList.end() ? found->
get() :
nullptr;
462 if (pdf && dset && (0. != dset->
sumEntries() || processEmptyDataSets())) {
463 ccoutI(Fitting) <<
"RooAbsTestStatistic::initSimMode: creating slave calculator #" << _gofArray.
size() <<
" for state " << catName
464 <<
" (" << dset->
numEntries() <<
" dataset entries)" << std::endl;
470 RooAbsReal &actualPdf = binnedInfo.binnedPdf ? *binnedInfo.binnedPdf : *pdf;
475 cfg.addCoefRangeName = addCoefRangeName;
476 cfg.interleave = _mpinterl;
477 cfg.verbose = _verbose;
478 cfg.splitCutRange = _splitRange;
479 cfg.binnedL = binnedInfo.isBinnedL;
480 cfg.takeGlobalObservablesFromData = _takeGlobalObservablesFromData;
484 if(
auto thisAsRooAbsOptTestStatistic =
dynamic_cast<RooAbsOptTestStatistic const*
>(
this)) {
485 cfg.integrateOverBinsPrecision = thisAsRooAbsOptTestStatistic->_integrateBinsPrecision;
489 _gofArray.emplace_back(create(catName.c_str(),catName.c_str(),actualPdf,*dset,*projDeps,cfg));
504 _gofArray.back()->recursiveRedirectServers(selTargetParams);
507 for(
auto& gof : _gofArray) {
508 gof->setSimCount(_gofArray.size());
510 coutI(Fitting) <<
"RooAbsTestStatistic::initSimMode: created " << _gofArray.
size() <<
" slave calculators." << std::endl;
519bool RooAbsTestStatistic::setData(
RooAbsData& indata,
bool cloneData)
522 if (isOffsetting()) {
523 enableOffsetting(
false);
524 enableOffsetting(
true);
530 return setDataSlave(indata, cloneData);
534 for(
auto& gof : _gofArray) {
536 gof->setDataSlave(*compData, cloneData);
540 for(
auto& gof : _gofArray) {
541 gof->setDataSlave(indata, cloneData);
544 std::vector<std::unique_ptr<RooAbsData>> dlist{indata.
split(*
static_cast<RooSimultaneous*
>(_func), processEmptyDataSets())};
546 for(
auto& gof : _gofArray) {
547 auto found = std::find_if(dlist.begin(), dlist.end(), [&](
auto const &item) {
548 return strcmp(gof->GetName(), item->GetName()) == 0;
550 RooAbsData *compData = found != dlist.end() ? found->
get() :
nullptr;
552 gof->setDataSlave(*compData,
false,
true);
554 coutE(DataHandling) <<
"RooAbsTestStatistic::setData(" <<
GetName() <<
") ERROR: Cannot find component data for state " << gof->GetName() << std::endl;
561 coutF(DataHandling) <<
"RooAbsTestStatistic::setData(" <<
GetName() <<
") FATAL: setData() is not supported in multi-processor mode" << std::endl;
562 throw std::runtime_error(
"RooAbsTestStatistic::setData is not supported in MPMaster mode");
571void RooAbsTestStatistic::enableOffsetting(
bool flag)
575 const_cast<RooAbsTestStatistic*
>(
this)->
initialize() ;
589 for(
auto& gof : _gofArray) {
590 gof->enableOffsetting(flag);
595 for (
Int_t i = 0; i < _nCPU; ++i) {
596 _mpfeArray[i]->enableOffsetting(flag);
603double RooAbsTestStatistic::getCarry()
const
604{
return _evalCarry; }
int Int_t
Signed integer 4 bytes (int)
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
Abstract base class for objects that represent a discrete value that can be set from the outside,...
Abstract container object that can hold multiple RooAbsArg objects.
Storage_t::size_type size() const
Abstract base class for binned and unbinned datasets.
virtual double sumEntries() const =0
Return effective number of entries in dataset, i.e., sum all weights.
virtual const RooArgSet * get() const
std::vector< std::unique_ptr< RooAbsData > > split(const RooAbsCategory &splitCat, bool createEmptyDataSets=false) const
Split the dataset into subsets based on states of a categorical variable in this dataset.
bool canSplitFast() const
RooAbsData * getSimData(const char *idxstate)
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Abstract interface for all probability density functions.
Abstract base class for objects that represent a real value and implements functionality common to al...
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
Function that is called at the end of redirectServers().
RooArgSet is a container object that can hold multiple RooAbsArg objects.
RooArgSet * selectCommon(const RooAbsCollection &refColl) const
Use RooAbsCollection::selecCommon(), but return as RooArgSet.
Object to represent discrete states.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
bool indexCatIsObservable(RooArgSet const &vars) const
Check if the index category is among the variables vars, matching by name.
const RooAbsCategoryLValue & indexCat() const
std::string getRangeNameForSimComponent(std::string const &rangeName, bool splitRange, std::string const &catName)
BinnedLOutput getBinnedL(RooAbsPdf const &pdf)
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
std::string GetName(TCppScope_t)
static uint64_t sum(uint64_t i)