59using std::endl, std::ostream;
90 const RooArgSet& projDeps, RooAbsTestStatistic::Configuration
const& cfg) :
92 _paramSet(
"paramSet",
"Set of parameters",this),
95 _projDeps(static_cast<
RooArgSet*>(projDeps.Clone())),
96 _rangeName(cfg.rangeName),
97 _addCoefRangeName(cfg.addCoefRangeName),
98 _splitRange(cfg.splitCutRange),
101 _gofOpMode{(cfg.nCPU>1 || cfg.nCPU==-1) ? MPMaster : (dynamic_cast<
RooSimultaneous*>(_func) ? SimMaster : Slave)},
102 _nEvents{data.numEntries()},
103 _nCPU(cfg.nCPU != -1 ? cfg.nCPU : 1),
104 _mpinterl(cfg.interleave),
105 _takeGlobalObservablesFromData{cfg.takeGlobalObservablesFromData}
108 _paramSet.add(*std::unique_ptr<RooArgSet>{real.
getParameters(&data)});
116RooAbsTestStatistic::RooAbsTestStatistic(
const RooAbsTestStatistic& other,
const char*
name) :
118 _paramSet(
"paramSet",
"Set of parameters",this),
121 _projDeps(static_cast<
RooArgSet*>(other._projDeps->Clone())),
122 _rangeName(other._rangeName),
123 _addCoefRangeName(other._addCoefRangeName),
124 _splitRange(other._splitRange),
125 _verbose(other._verbose),
127 _gofOpMode{(other._nCPU>1 || other._nCPU==-1) ? MPMaster : (dynamic_cast<
RooSimultaneous*>(_func) ? SimMaster : Slave)},
128 _nEvents{_data->numEntries()},
129 _nCPU(other._nCPU != -1 ? other._nCPU : 1),
130 _mpinterl(other._mpinterl),
131 _doOffset(other._doOffset),
132 _takeGlobalObservablesFromData{other._takeGlobalObservablesFromData},
133 _offset(other._offset),
134 _evalCarry(other._evalCarry)
137 _paramSet.add(other._paramSet) ;
145RooAbsTestStatistic::~RooAbsTestStatistic()
147 if (MPMaster == _gofOpMode && _init) {
148 for (
Int_t i = 0; i < _nCPU; ++i)
delete _mpfeArray[i];
149 delete[] _mpfeArray ;
164double RooAbsTestStatistic::evaluate()
const
168 const_cast<RooAbsTestStatistic*
>(
this)->
initialize() ;
171 if (SimMaster == _gofOpMode) {
176 ret = combinedValue(
reinterpret_cast<RooAbsReal**
>(
const_cast<std::unique_ptr<RooAbsTestStatistic>*
>(_gofArray.data())),_gofArray.size());
181 for (
auto& gof : _gofArray) {
183 double y = gof->getValV();
184 carry += gof->getCarry();
186 const double t =
sum +
y;
187 carry = (t -
sum) -
y;
198 const double norm = globalNormalization();
205 }
else if (MPMaster == _gofOpMode) {
208 for (
Int_t i = 0; i < _nCPU; ++i) _mpfeArray[i]->calculate();
212 for (
Int_t i = 0; i < _nCPU; ++i) {
213 double y = _mpfeArray[i]->getValV();
214 carry += _mpfeArray[i]->getCarry();
216 const double t =
sum +
y;
217 carry = (t -
sum) -
y;
224 const double norm = globalNormalization();
234 Int_t nLast(_nEvents);
239 nFirst = _nEvents * _setNum / _numSets ;
240 nLast = _nEvents * (_setNum+1) / _numSets ;
257 throw std::logic_error(
"this should never happen");
261 runRecalculateCache(nFirst, nLast, nStep);
262 double ret = evaluatePartition(nFirst,nLast,nStep);
265 const double norm = globalNormalization();
282bool RooAbsTestStatistic::initialize()
284 if (_init)
return false;
286 if (MPMaster == _gofOpMode) {
287 initMPMode(_func,_data,_projDeps,_rangeName,_addCoefRangeName) ;
288 }
else if (SimMaster == _gofOpMode) {
289 initSimMode(
static_cast<RooSimultaneous*
>(_func),_data,_projDeps,_rangeName,_addCoefRangeName) ;
300bool RooAbsTestStatistic::redirectServersHook(
const RooAbsCollection& newServerList,
bool mustReplaceAll,
bool nameChange,
bool isRecursive)
302 if (SimMaster == _gofOpMode) {
304 for(
auto& gof : _gofArray) {
305 gof->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
307 }
else if (MPMaster == _gofOpMode&& _mpfeArray) {
309 for (
Int_t i = 0; i < _nCPU; ++i) {
311 _mpfeArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
325void RooAbsTestStatistic::printCompactTreeHook(
ostream& os,
const char*
indent)
327 if (SimMaster == _gofOpMode) {
329 os <<
indent <<
"RooAbsTestStatistic begin GOF contents" << std::endl ;
330 for (std::size_t i = 0; i < _gofArray.size(); ++i) {
332 indent2 +=
"[" + std::to_string(i) +
"] ";
333 _gofArray[i]->printCompactTreeHook(os,indent2);
335 os <<
indent <<
"RooAbsTestStatistic end GOF contents" << std::endl;
336 }
else if (MPMaster == _gofOpMode) {
347void RooAbsTestStatistic::constOptimizeTestStatistic(ConstOpCode opcode,
bool doAlsoTrackingOpt)
350 if (SimMaster == _gofOpMode) {
353 for (
auto& gof : _gofArray) {
357 gof->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
361 }
else if (MPMaster == _gofOpMode) {
362 for (
Int_t i = 0; i < _nCPU; ++i) {
363 _mpfeArray[i]->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
373void RooAbsTestStatistic::setMPSet(
Int_t inSetNum,
Int_t inNumSets)
375 _setNum = inSetNum; _numSets = inNumSets;
378 if (SimMaster == _gofOpMode) {
381 for(
auto& gof : _gofArray) {
382 gof->setMPSet(inSetNum,inNumSets);
393void RooAbsTestStatistic::initMPMode(
RooAbsReal* real,
RooAbsData* data,
const RooArgSet* projDeps, std::string
const& rangeName, std::string
const& addCoefRangeName)
395 _mpfeArray =
new pRooRealMPFE[_nCPU];
399 cfg.rangeName = rangeName;
400 cfg.addCoefRangeName = addCoefRangeName;
402 cfg.interleave = _mpinterl;
403 cfg.verbose = _verbose;
404 cfg.splitCutRange = _splitRange;
405 cfg.takeGlobalObservablesFromData = _takeGlobalObservablesFromData;
409 if(
auto thisAsRooAbsOptTestStatistic =
dynamic_cast<RooAbsOptTestStatistic const*
>(
this)) {
410 cfg.integrateOverBinsPrecision = thisAsRooAbsOptTestStatistic->_integrateBinsPrecision;
412 RooAbsTestStatistic* gof = create(GetName(),GetTitle(),*real,*data,*projDeps,cfg);
413 gof->recursiveRedirectServers(_paramSet);
415 for (
Int_t i = 0; i < _nCPU; ++i) {
416 gof->setMPSet(i,_nCPU);
417 gof->SetName(
Form(
"%s_GOF%d",GetName(),i));
418 gof->SetTitle(
Form(
"%s_GOF%d",GetTitle(),i));
420 ccoutD(Eval) <<
"RooAbsTestStatistic::initMPMode: starting remote server process #" << i << std::endl;
421 _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);
423 _mpfeArray[i]->initialize();
425 _mpfeArray[i]->followAsSlave(*_mpfeArray[0]);
428 _mpfeArray[_nCPU - 1]->addOwnedComponents(*gof);
429 coutI(Eval) <<
"RooAbsTestStatistic::initMPMode: started " << _nCPU <<
" remote server process." << std::endl;
444 std::string
const& rangeName, std::string
const& addCoefRangeName)
449 std::vector<std::unique_ptr<RooAbsData>> dsetList{
const_cast<RooAbsData*
>(data)->split(*simpdf,processEmptyDataSets())};
452 for (
const auto& catState : simCat) {
453 const std::string& catName = catState.first;
458 if(!rangeName.empty()) {
461 auto simCatAsRooCategory =
dynamic_cast<RooCategory*
>(&simCat);
462 if(simCatAsRooCategory && !simCatAsRooCategory->isStateInRange(rangeName.c_str(), catIndex)) {
469 auto found = std::find_if(dsetList.begin(), dsetList.end(), [&](
auto const &item) {
470 return catName == item->GetName();
472 RooAbsData *dset = found != dsetList.end() ? found->get() :
nullptr;
474 if (pdf && dset && (0. != dset->
sumEntries() || processEmptyDataSets())) {
475 ccoutI(Fitting) <<
"RooAbsTestStatistic::initSimMode: creating slave calculator #" << _gofArray.size() <<
" for state " << catName
476 <<
" (" << dset->
numEntries() <<
" dataset entries)" << std::endl;
482 RooAbsReal &actualPdf = binnedInfo.binnedPdf ? *binnedInfo.binnedPdf : *pdf;
487 cfg.addCoefRangeName = addCoefRangeName;
488 cfg.interleave = _mpinterl;
489 cfg.verbose = _verbose;
490 cfg.splitCutRange = _splitRange;
491 cfg.binnedL = binnedInfo.isBinnedL;
492 cfg.takeGlobalObservablesFromData = _takeGlobalObservablesFromData;
496 if(
auto thisAsRooAbsOptTestStatistic =
dynamic_cast<RooAbsOptTestStatistic const*
>(
this)) {
497 cfg.integrateOverBinsPrecision = thisAsRooAbsOptTestStatistic->_integrateBinsPrecision;
501 _gofArray.emplace_back(create(catName.c_str(),catName.c_str(),actualPdf,*dset,*projDeps,cfg));
516 _gofArray.back()->recursiveRedirectServers(selTargetParams);
519 for(
auto& gof : _gofArray) {
520 gof->setSimCount(_gofArray.size());
522 coutI(Fitting) <<
"RooAbsTestStatistic::initSimMode: created " << _gofArray.
size() <<
" slave calculators." << std::endl;
531bool RooAbsTestStatistic::setData(
RooAbsData& indata,
bool cloneData)
534 if (isOffsetting()) {
535 enableOffsetting(
false);
536 enableOffsetting(
true);
542 return setDataSlave(indata, cloneData);
546 for(
auto& gof : _gofArray) {
548 gof->setDataSlave(*compData, cloneData);
552 for(
auto& gof : _gofArray) {
553 gof->setDataSlave(indata, cloneData);
556 std::vector<std::unique_ptr<RooAbsData>> dlist{indata.
split(*
static_cast<RooSimultaneous*
>(_func), processEmptyDataSets())};
558 for(
auto& gof : _gofArray) {
559 auto found = std::find_if(dlist.begin(), dlist.end(), [&](
auto const &item) {
560 return strcmp(gof->GetName(), item->GetName()) == 0;
562 RooAbsData *compData = found != dlist.end() ? found->get() :
nullptr;
564 gof->setDataSlave(*compData,
false,
true);
566 coutE(DataHandling) <<
"RooAbsTestStatistic::setData(" << GetName() <<
") ERROR: Cannot find component data for state " << gof->GetName() << std::endl;
573 coutF(DataHandling) <<
"RooAbsTestStatistic::setData(" << GetName() <<
") FATAL: setData() is not supported in multi-processor mode" << std::endl;
574 throw std::runtime_error(
"RooAbsTestStatistic::setData is not supported in MPMaster mode");
583void RooAbsTestStatistic::enableOffsetting(
bool flag)
587 const_cast<RooAbsTestStatistic*
>(
this)->
initialize() ;
601 for(
auto& gof : _gofArray) {
602 gof->enableOffsetting(flag);
607 for (
Int_t i = 0; i < _nCPU; ++i) {
608 _mpfeArray[i]->enableOffsetting(flag);
615double RooAbsTestStatistic::getCarry()
const
616{
return _evalCarry; }
int Int_t
Signed integer 4 bytes (int).
static void indent(ostringstream &buf, int indent_level)
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,...
int value_type
The type used to denote a specific category state.
std::size_t size() const
Number of states defined.
Abstract container object that can hold multiple RooAbsArg objects.
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.
const RooAbsCategoryLValue & indexCat() const
std::string getRangeNameForSimComponent(std::string const &rangeName, bool splitRange, std::string const &catName)
BinnedLOutput getBinnedL(RooAbsPdf const &pdf)
static uint64_t sum(uint64_t i)