Logo ROOT  
Reference Guide
RooAbsOptTestStatistic.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooAbsOptTestStatistic.cxx
19\class RooAbsOptTestStatistic
20\ingroup Roofitcore
21
22RooAbsOptTestStatistic is the abstract base class for test
23statistics objects that evaluate a function or PDF at each point of a given
24dataset. This class provides generic optimizations, such as
25caching and precalculation of constant terms that can be made for
26all such quantities.
27
28Implementations should define evaluatePartition(), which calculates the
29value of a (sub)range of the dataset and optionally combinedValue(),
30which combines the values calculated for each partition. If combinedValue()
31is not overloaded, the default implementation will add the partition results
32to obtain the combined result.
33
34Support for calculation in partitions is needed to allow multi-core
35parallelized calculation of test statistics.
36**/
37
38#include "RooFit.h"
39
40#include "Riostream.h"
41#include <string.h>
42
43
45#include "RooMsgService.h"
46#include "RooAbsPdf.h"
47#include "RooAbsData.h"
48#include "RooDataHist.h"
49#include "RooArgSet.h"
50#include "RooRealVar.h"
51#include "RooErrorHandler.h"
52#include "RooGlobalFunc.h"
53#include "RooBinning.h"
54#include "RooAbsDataStore.h"
55#include "RooCategory.h"
56#include "RooDataSet.h"
57#include "RooProdPdf.h"
58#include "RooAddPdf.h"
59#include "RooProduct.h"
60#include "RooRealSumPdf.h"
61#include "RooTrace.h"
62#include "RooVectorDataStore.h"
63#include "RooBinSamplingPdf.h"
64
65using namespace std;
66
68;
69
70
71////////////////////////////////////////////////////////////////////////////////
72/// Default Constructor
73
75{
76 // Initialize all non-persisted data members
77
78 _funcObsSet = 0 ;
79 _funcCloneSet = 0 ;
80 _funcClone = 0 ;
81
82 _normSet = 0 ;
83 _projDeps = 0 ;
84
85 _origFunc = 0 ;
86 _origData = 0 ;
87
88 _ownData = kTRUE ;
89 _sealed = kFALSE ;
91}
92
93
94
95////////////////////////////////////////////////////////////////////////////////
96/// Create a test statistic, and optimise its calculation.
97/// \param[in] name Name of the instance.
98/// \param[in] title Title (for e.g. plotting).
99/// \param[in] real Function to evaluate.
100/// \param[in] indata Dataset for which to compute test statistic.
101/// \param[in] projDeps A set of projected observables.
102/// \param[in] rangeName If not null, only events in the dataset inside the range will be used in the test
103/// statistic calculation.
104/// \param[in] addCoefRangeName If not null, all RooAddPdf components of `real` will be
105/// instructed to fix their fraction definitions to the given named range.
106/// \param[in] nCPU If > 1, the test statistic calculation will be parallelised over multiple processes. By default, the data
107/// is split with 'bulk' partitioning (each process calculates a contiguous block of fraction 1/nCPU
108/// of the data). For binned data, this approach may be suboptimal as the number of bins with >0 entries
109/// in each processing block may vary greatly; thereby distributing the workload rather unevenly.
110/// \param[in] interleave Strategy how to distribute events among workers. If an interleave partitioning strategy is used where each partition
111/// i takes all bins for which (ibin % ncpu == i), an even distribution of work is more likely.
112/// \param[in] splitCutRange If true, a different rangeName constructed as `rangeName_{catName}` will be used
113/// as range definition for each index state of a RooSimultaneous.
114/// \param[in] cloneInputData Not used. Data is always cloned.
115/// \param[in] integrateOverBinsPrecision If > 0, PDF in binned fits are integrated over the bins. This sets the precision. If = 0,
116/// only unbinned PDFs fit to RooDataHist are integrated. If < 0, PDFs are never integrated.
118 RooAbsData& indata, const RooArgSet& projDeps,
120 RooAbsTestStatistic(name,title,real,indata,projDeps,cfg),
121 _projDeps(0),
122 _sealed(kFALSE),
123 _optimized(kFALSE),
124 _integrateBinsPrecision(cfg.integrateOverBinsPrecision)
125{
126 // Don't do a thing in master mode
127
128 if (operMode()!=Slave) {
129 _funcObsSet = 0 ;
130 _funcCloneSet = 0 ;
131 _funcClone = 0 ;
132 _normSet = 0 ;
133 _projDeps = 0 ;
134 _origFunc = 0 ;
135 _origData = 0 ;
136 _ownData = kFALSE ;
137 _sealed = kFALSE ;
138 return ;
139 }
140
141 _origFunc = 0 ; //other._origFunc ;
142 _origData = 0 ; // other._origData ;
143
144 initSlave(real, indata, projDeps, _rangeName.c_str(), _addCoefRangeName.c_str()) ;
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Copy constructor
149
151 RooAbsTestStatistic(other,name), _sealed(other._sealed), _sealNotice(other._sealNotice), _optimized(kFALSE),
152 _integrateBinsPrecision(other._integrateBinsPrecision)
153{
154 // Don't do a thing in master mode
155 if (operMode()!=Slave) {
156
157 _funcObsSet = 0 ;
158 _funcCloneSet = 0 ;
159 _funcClone = 0 ;
160 _normSet = other._normSet ? ((RooArgSet*) other._normSet->snapshot()) : 0 ;
161 _projDeps = 0 ;
162 _origFunc = 0 ;
163 _origData = 0 ;
164 _ownData = kFALSE ;
165 return ;
166 }
167
168 _origFunc = 0 ; //other._origFunc ;
169 _origData = 0 ; // other._origData ;
170 _projDeps = 0 ;
171
172 initSlave(*other._funcClone,*other._dataClone,other._projDeps?*other._projDeps:RooArgSet(),other._rangeName.c_str(),other._addCoefRangeName.c_str()) ;
173}
174
175
176
177////////////////////////////////////////////////////////////////////////////////
178
179void RooAbsOptTestStatistic::initSlave(RooAbsReal& real, RooAbsData& indata, const RooArgSet& projDeps, const char* rangeName,
180 const char* addCoefRangeName) {
181 // ******************************************************************
182 // *** PART 1 *** Clone incoming pdf, attach to each other *
183 // ******************************************************************
184
185 // Clone FUNC
186 _funcClone = static_cast<RooAbsReal*>(real.cloneTree());
187 _funcCloneSet = 0 ;
188
189 // Attach FUNC to data set
191
192 if (_funcClone->getAttribute("BinnedLikelihood")) {
193 _funcClone->setAttribute("BinnedLikelihoodActive") ;
194 }
195
196 // Reattach FUNC to original parameters
197 RooArgSet* origParams = (RooArgSet*) real.getParameters(indata) ;
199
200 // Mark all projected dependents as such
201 if (projDeps.getSize()>0) {
202 RooArgSet *projDataDeps = (RooArgSet*) _funcObsSet->selectCommon(projDeps) ;
203 projDataDeps->setAttribAll("projectedDependent") ;
204 delete projDataDeps ;
205 }
206
207 // If PDF is a RooProdPdf (with possible constraint terms)
208 // analyze pdf for actual parameters (i.e those in unconnected constraint terms should be
209 // ignored as here so that the test statistic will not be recalculated if those
210 // are changed
211 RooProdPdf* pdfWithCons = dynamic_cast<RooProdPdf*>(_funcClone) ;
212 if (pdfWithCons) {
213
214 RooArgSet* connPars = pdfWithCons->getConnectedParameters(*indata.get()) ;
215 // Add connected parameters as servers
217 _paramSet.add(*connPars) ;
218 delete connPars ;
219
220 } else {
221 // Add parameters as servers
222 _paramSet.add(*origParams) ;
223 }
224
225
226 delete origParams ;
227
228 // Store normalization set
229 _normSet = (RooArgSet*) indata.get()->snapshot(kFALSE) ;
230
231 // Expand list of observables with any observables used in parameterized ranges.
232 // This NEEDS to be a counting loop since we are inserting during the loop.
233 for (std::size_t i = 0; i < _funcObsSet->size(); ++i) {
234 auto realDepRLV = dynamic_cast<const RooAbsRealLValue*>((*_funcObsSet)[i]);
235 if (realDepRLV && realDepRLV->isDerived()) {
236 RooArgSet tmp2;
237 realDepRLV->leafNodeServerList(&tmp2, 0, kTRUE);
238 _funcObsSet->add(tmp2,kTRUE);
239 }
240 }
241
242
243
244 // ******************************************************************
245 // *** PART 2 *** Clone and adjust incoming data, attach to PDF *
246 // ******************************************************************
247
248 // Check if the fit ranges of the dependents in the data and in the FUNC are consistent
249 const RooArgSet* dataDepSet = indata.get() ;
250 for (const auto arg : *_funcObsSet) {
251
252 // Check that both dataset and function argument are of type RooRealVar
253 RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
254 if (!realReal) continue ;
255 RooRealVar* datReal = dynamic_cast<RooRealVar*>(dataDepSet->find(realReal->GetName())) ;
256 if (!datReal) continue ;
257
258 // Check that range of observables in pdf is equal or contained in range of observables in data
259
260 if (!realReal->getBinning().lowBoundFunc() && realReal->getMin()<(datReal->getMin()-1e-6)) {
261 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR minimum of FUNC observable " << arg->GetName()
262 << "(" << realReal->getMin() << ") is smaller than that of "
263 << arg->GetName() << " in the dataset (" << datReal->getMin() << ")" << endl ;
265 return ;
266 }
267
268 if (!realReal->getBinning().highBoundFunc() && realReal->getMax()>(datReal->getMax()+1e-6)) {
269 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR maximum of FUNC observable " << arg->GetName()
270 << " is larger than that of " << arg->GetName() << " in the dataset" << endl ;
272 return ;
273 }
274 }
275
276 // Copy data and strip entries lost by adjusted fit range, _dataClone ranges will be copied from realDepSet ranges
277 if (rangeName && strlen(rangeName)) {
279 // cout << "RooAbsOptTestStatistic: reducing dataset to fit in range named " << rangeName << " resulting dataset has " << _dataClone->sumEntries() << " events" << endl ;
280 } else {
281 _dataClone = (RooAbsData*) indata.Clone() ;
282 }
283 _ownData = kTRUE ;
284
285
286 // ******************************************************************
287 // *** PART 3 *** Make adjustments for fit ranges, if specified *
288 // ******************************************************************
289
290 std::unique_ptr<RooArgSet> origObsSet( real.getObservables(indata) );
291 RooArgSet* dataObsSet = (RooArgSet*) _dataClone->get() ;
292 if (rangeName && strlen(rangeName)) {
293 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") constructing test statistic for sub-range named " << rangeName << endl ;
294
295 bool observablesKnowRange = false;
296 // Adjust FUNC normalization ranges to requested fitRange, store original ranges for RooAddPdf coefficient interpretation
297 for (const auto arg : *_funcObsSet) {
298
299 RooRealVar* realObs = dynamic_cast<RooRealVar*>(arg) ;
300 if (realObs) {
301
302 observablesKnowRange |= realObs->hasRange(rangeName);
303
304 // If no explicit range is given for RooAddPdf coefficients, create explicit named range equivalent to original observables range
305 if (!(addCoefRangeName && strlen(addCoefRangeName))) {
306 realObs->setRange(Form("NormalizationRangeFor%s",rangeName),realObs->getMin(),realObs->getMax()) ;
307 }
308
309 // Adjust range of function observable to those of given named range
310 realObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ;
311
312 // Adjust range of data observable to those of given named range
313 RooRealVar* dataObs = (RooRealVar*) dataObsSet->find(realObs->GetName()) ;
314 dataObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ;
315
316 // Keep track of list of fit ranges in string attribute fit range of original p.d.f.
317 if (!_splitRange) {
318 const std::string fitRangeName = std::string("fit_") + GetName();
319 const char* origAttrib = real.getStringAttribute("fitrange") ;
320 std::string newAttr = origAttrib ? origAttrib : "";
321
322 if (newAttr.find(fitRangeName) == std::string::npos) {
323 newAttr += (newAttr.empty() ? "" : ",") + fitRangeName;
324 }
325 real.setStringAttribute("fitrange", newAttr.c_str());
326 RooRealVar* origObs = (RooRealVar*) origObsSet->find(arg->GetName()) ;
327 if (origObs) {
328 origObs->setRange(fitRangeName.c_str(), realObs->getMin(rangeName), realObs->getMax(rangeName));
329 }
330 }
331 }
332 }
333
334 if (!observablesKnowRange)
335 coutW(Fitting) << "None of the fit observables seem to know the range '" << rangeName << "'. This means that the full range will be used." << std::endl;
336 }
337
338
339 // ******************************************************************
340 // *** PART 3.2 *** Binned fits *
341 // ******************************************************************
342
343 // If dataset is binned, activate caching of bins that are invalid because the're outside the
344 // updated range definition (WVE need to add virtual interface here)
345 RooDataHist* tmph = dynamic_cast<RooDataHist*>(_dataClone) ;
346 if (tmph) {
347 tmph->cacheValidEntries() ;
348 }
349
351
352
353 // Fix RooAddPdf coefficients to original normalization range
354 if (rangeName && strlen(rangeName)) {
355
356 // WVE Remove projected dependents from normalization
358
359 if (addCoefRangeName && strlen(addCoefRangeName)) {
360 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
361 << ") fixing interpretation of coefficients of any RooAddPdf component to range " << addCoefRangeName << endl ;
362 _funcClone->fixAddCoefRange(addCoefRangeName,kFALSE) ;
363 } else {
364 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
365 << ") fixing interpretation of coefficients of any RooAddPdf to full domain of observables " << endl ;
366 _funcClone->fixAddCoefRange(Form("NormalizationRangeFor%s",rangeName),kFALSE) ;
367 }
368 }
369
370
371 // This is deferred from part 2 - but must happen after part 3 - otherwise invalid bins cannot be properly marked in cacheValidEntries
374
375
376
377
378 // *********************************************************************
379 // *** PART 4 *** Adjust normalization range for projected observables *
380 // *********************************************************************
381
382 // Remove projected dependents from normalization set
383 if (projDeps.getSize()>0) {
384
385 _projDeps = (RooArgSet*) projDeps.snapshot(kFALSE) ;
386
387 //RooArgSet* tobedel = (RooArgSet*) _normSet->selectCommon(*_projDeps) ;
389
390 // Mark all projected dependents as such
392 projDataDeps->setAttribAll("projectedDependent") ;
393 delete projDataDeps ;
394 }
395
396
397 coutI(Optimization) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") optimizing internal clone of p.d.f for likelihood evaluation."
398 << "Lazy evaluation and associated change tracking will disabled for all nodes that depend on observables" << endl ;
399
400
401 // *********************************************************************
402 // *** PART 4 *** Finalization and activation of optimization *
403 // *********************************************************************
404
405 // Redirect pointers of base class to clone
406 _func = _funcClone ;
407 _data = _dataClone ;
408
410
412
413 // It would be unusual if the global observables are used in the likelihood
414 // outside of the constraint terms, but if they are we have to be consistent
415 // and also redirect them to the snapshots in the dataset if appropriate.
418 }
419
420}
421
422
423////////////////////////////////////////////////////////////////////////////////
424/// Destructor
425
427{
428 if (operMode()==Slave) {
429 delete _funcClone ;
430 delete _funcObsSet ;
431 if (_projDeps) {
432 delete _projDeps ;
433 }
434 if (_ownData) {
435 delete _dataClone ;
436 }
437 }
438 delete _normSet ;
439}
440
441
442
443////////////////////////////////////////////////////////////////////////////////
444/// Method to combined test statistic results calculated into partitions into
445/// the global result. This default implementation adds the partition return
446/// values
447
449{
450 // Default implementation returns sum of components
451 Double_t sum(0), carry(0);
452 for (Int_t i = 0; i < n; ++i) {
453 Double_t y = array[i]->getValV();
454 carry += reinterpret_cast<RooAbsOptTestStatistic*>(array[i])->getCarry();
455 y -= carry;
456 const Double_t t = sum + y;
457 carry = (t - sum) - y;
458 sum = t;
459 }
460 _evalCarry = carry;
461 return sum ;
462}
463
464
465
466////////////////////////////////////////////////////////////////////////////////
467/// Catch server redirect calls and forward to internal clone of function
468
469Bool_t RooAbsOptTestStatistic::redirectServersHook(const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
470{
471 RooAbsTestStatistic::redirectServersHook(newServerList,mustReplaceAll,nameChange,isRecursive) ;
472 if (operMode()!=Slave) return kFALSE ;
473 Bool_t ret = _funcClone->recursiveRedirectServers(newServerList,kFALSE,nameChange) ;
474 return ret ;
475}
476
477
478
479////////////////////////////////////////////////////////////////////////////////
480/// Catch print hook function and forward to function clone
481
483{
485 if (operMode()!=Slave) return ;
486 TString indent2(indent) ;
487 indent2 += "opt >>" ;
488 _funcClone->printCompactTree(os,indent2.Data()) ;
489 os << indent2 << " dataset clone = " << _dataClone << " first obs = " << _dataClone->get()->first() << endl ;
490}
491
492
493
494////////////////////////////////////////////////////////////////////////////////
495/// Driver function to propagate constant term optimizations in test statistic.
496/// If code Activate is sent, constant term optimization will be executed.
497/// If code Deactivate is sent, any existing constant term optimizations will
498/// be abandoned. If codes ConfigChange or ValueChange are sent, any existing
499/// constant term optimizations will be redone.
500
502{
503 // cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump BEFORE const-opt" << endl ;
504 // _funcClone->Print("t") ;
505
506 RooAbsTestStatistic::constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
507 if (operMode()!=Slave) return ;
508
509 if (_dataClone->hasFilledCache() && _dataClone->store()->cacheOwner()!=this) {
510 if (opcode==Activate) {
511 cxcoutW(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
512 << ") dataset cache is owned by another object, no constant term optimization can be applied" << endl ;
513 }
514 return ;
515 }
516
517 if (!allowFunctionCache()) {
518 if (opcode==Activate) {
519 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
520 << ") function caching prohibited by test statistic, no constant term optimization is applied" << endl ;
521 }
522 return ;
523 }
524
525 if (_dataClone->hasFilledCache() && opcode==Activate) {
526 opcode=ValueChange ;
527 }
528
529 switch(opcode) {
530 case Activate:
531 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
532 << ") optimizing evaluation of test statistic by finding all nodes in p.d.f that depend exclusively"
533 << " on observables and constant parameters and precalculating their values" << endl ;
534 optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
535 break ;
536
537 case DeActivate:
538 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
539 << ") deactivating optimization of constant terms in test statistic" << endl ;
541 break ;
542
543 case ConfigChange:
544 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
545 << ") one ore more parameter were changed from constant to floating or vice versa, "
546 << "re-evaluating constant term optimization" << endl ;
548 optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
549 break ;
550
551 case ValueChange:
552 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
553 << ") the value of one ore more constant parameter were changed re-evaluating constant term optimization" << endl ;
554 // Request a forcible cache update of all cached nodes
556
557 break ;
558 }
559
560// cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump AFTER const-opt" << endl ;
561// _funcClone->Print("t") ;
562}
563
564
565
566////////////////////////////////////////////////////////////////////////////////
567/// This method changes the value caching logic for all nodes that depends on any of the observables
568/// as defined by the given dataset. When evaluating a test statistic constructed from the RooAbsReal
569/// with a dataset the observables are guaranteed to change with every call, thus there is no point
570/// in tracking these changes which result in a net overhead. Thus for observable-dependent nodes,
571/// the evaluation mechanism is changed from being dependent on a 'valueDirty' flag to guaranteed evaluation.
572/// On the dataset side, the observables objects are modified to no longer send valueDirty messages
573/// to their client
574
576{
577// cout << "RooAbsOptTestStatistic::optimizeCaching(" << GetName() << "," << this << ")" << endl ;
578
579 // Trigger create of all object caches now in nodes that have deferred object creation
580 // so that cache contents can be processed immediately
582
583 // Set value caching mode for all nodes that depend on any of the observables to ADirty
585
586 // Disable propagation of dirty state flags for observables
588
589 // Disable reading of observables that are not used
591}
592
593
594
595////////////////////////////////////////////////////////////////////////////////
596/// Driver function to activate global constant term optimization.
597/// If activated, constant terms are found and cached with the dataset.
598/// The operation mode of cached nodes is set to AClean meaning that
599/// their getVal() call will never result in an evaluate call.
600/// Finally the branches in the dataset that correspond to observables
601/// that are exclusively used in constant terms are disabled as
602/// they serve no more purpose
603
605{
606 if(activate) {
607
608 if (_optimized) {
609 return ;
610 }
611
612 // Trigger create of all object caches now in nodes that have deferred object creation
613 // so that cache contents can be processed immediately
615
616 // Apply tracking optimization here. Default strategy is to track components
617 // of RooAddPdfs and RooRealSumPdfs. If these components are a RooProdPdf
618 // or a RooProduct respectively, track the components of these products instead
619 // of the product term
620 RooArgSet trackNodes ;
621
622
623 // Add safety check here - applyTrackingOpt will only be applied if present
624 // dataset is constructed in terms of a RooVectorDataStore
625 if (applyTrackingOpt) {
626 if (!dynamic_cast<RooVectorDataStore*>(_dataClone->store())) {
627 coutW(Optimization) << "RooAbsOptTestStatistic::optimizeConstantTerms(" << GetName()
628 << ") WARNING Cache-and-track optimization (Optimize level 2) is only available for datasets"
629 << " implement in terms of RooVectorDataStore - ignoring this option for current dataset" << endl ;
630 applyTrackingOpt = kFALSE ;
631 }
632 }
633
634 if (applyTrackingOpt) {
635 RooArgSet branches ;
636 _funcClone->branchNodeServerList(&branches) ;
637 for (auto arg : branches) {
638 arg->setCacheAndTrackHints(trackNodes);
639 }
640 // Do not set CacheAndTrack on constant expressions
641 RooArgSet* constNodes = (RooArgSet*) trackNodes.selectByAttrib("Constant",kTRUE) ;
642 trackNodes.remove(*constNodes) ;
643 delete constNodes ;
644
645 // Set CacheAndTrack flag on all remaining nodes
646 trackNodes.setAttribAll("CacheAndTrack",kTRUE) ;
647 }
648
649 // Find all nodes that depend exclusively on constant parameters
651
653
654 // Cache constant nodes with dataset - also cache entries corresponding to zero-weights in data when using BinnedLikelihood
655 _dataClone->cacheArgs(this,_cachedNodes,_normSet,!_funcClone->getAttribute("BinnedLikelihood")) ;
656
657 // Put all cached nodes in AClean value caching mode so that their evaluate() is never called
658 for (auto cacheArg : _cachedNodes) {
659 cacheArg->setOperMode(RooAbsArg::AClean) ;
660 }
661
662 RooArgSet* constNodes = (RooArgSet*) _cachedNodes.selectByAttrib("ConstantExpressionCached",kTRUE) ;
663 RooArgSet actualTrackNodes(_cachedNodes) ;
664 actualTrackNodes.remove(*constNodes) ;
665 if (constNodes->getSize()>0) {
666 if (constNodes->getSize()<20) {
667 coutI(Minimization) << " The following expressions have been identified as constant and will be precalculated and cached: " << *constNodes << endl ;
668 } else {
669 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions have been identified as constant and will be precalculated and cached." << endl ;
670 }
671 }
672 if (actualTrackNodes.getSize()>0) {
673 if (actualTrackNodes.getSize()<20) {
674 coutI(Minimization) << " The following expressions will be evaluated in cache-and-track mode: " << actualTrackNodes << endl ;
675 } else {
676 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions will be evaluated in cache-and-track-mode." << endl ;
677 }
678 }
679 delete constNodes ;
680
681 // Disable reading of observables that are no longer used
683
684 _optimized = kTRUE ;
685
686 } else {
687
688 // Delete the cache
690
691 // Reactivate all tree branches
693
694 // Reset all nodes to ADirty
696
697 // Disable propagation of dirty state flags for observables
699
701
702
704 }
705}
706
707
708
709////////////////////////////////////////////////////////////////////////////////
710/// Change dataset that is used to given one. If cloneData is kTRUE, a clone of
711/// in the input dataset is made. If the test statistic was constructed with
712/// a range specification on the data, the cloneData argument is ignored and
713/// the data is always cloned.
715{
716
717 if (operMode()==SimMaster) {
718 //cout << "ROATS::setDataSlave() ERROR this is SimMaster _funcClone = " << _funcClone << endl ;
719 return kFALSE ;
720 }
721
722 //cout << "ROATS::setDataSlave() new dataset size = " << indata.numEntries() << endl ;
723 //indata.Print("v") ;
724
725
726 // If the current dataset is owned, transfer the ownership to unique pointer
727 // that will get out of scope at the end of this function. We can't delete it
728 // right now, because there might be global observables in the model that
729 // first need to be redirected to the new dataset with a later call to
730 // RooAbsArg::recursiveRedirectServers.
731 std::unique_ptr<RooAbsData> oldOwnedData;
732 if (_ownData) {
733 oldOwnedData.reset(_dataClone);
734 _dataClone = nullptr ;
735 }
736
737 if (!cloneData && _rangeName.size()>0) {
738 coutW(InputArguments) << "RooAbsOptTestStatistic::setData(" << GetName() << ") WARNING: test statistic was constructed with range selection on data, "
739 << "ignoring request to _not_ clone the input dataset" << endl ;
740 cloneData = kTRUE ;
741 }
742
743 if (cloneData) {
744 // Cloning input dataset
745 if (_rangeName.size()==0) {
746 _dataClone = (RooAbsData*) indata.reduce(*indata.get()) ;
747 } else {
749 }
750 _ownData = kTRUE ;
751
752 } else {
753
754 // Taking input dataset
755 _dataClone = &indata ;
756 _ownData = ownNewData ;
757
758 }
759
760 // Attach function clone to dataset
763 _data = _dataClone ;
764
765 // ReCache constant nodes with dataset
766 if (_cachedNodes.getSize()>0) {
768 }
769
770 // Adjust internal event count
771 setEventCount(indata.numEntries()) ;
772
773 setValueDirty() ;
774
775 // It would be unusual if the global observables are used in the likelihood
776 // outside of the constraint terms, but if they are we have to be consistent
777 // and also redirect them to the snapshots in the dataset if appropriate.
780 }
781
782 return kTRUE ;
783}
784
785
786
787
788////////////////////////////////////////////////////////////////////////////////
789
791{
792 if (_sealed) {
793 Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
794 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
795 << ") WARNING: object sealed by creator - access to data is not permitted: "
796 << (notice?sealNotice():"<no user notice>") << endl ;
797 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
798 return dummy ;
799 }
800 return *_dataClone ;
801}
802
803
804////////////////////////////////////////////////////////////////////////////////
805
807{
808 if (_sealed) {
809 Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
810 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
811 << ") WARNING: object sealed by creator - access to data is not permitted: "
812 << (notice?sealNotice():"<no user notice>") << endl ;
813 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
814 return dummy ;
815 }
816 return *_dataClone ;
817}
818
819
820////////////////////////////////////////////////////////////////////////////////
821/// Inspect PDF to find out if we are doing a binned fit to a 1-dimensional unbinned PDF.
822/// If this is the case, enable finer sampling of bins by wrapping PDF into a RooBinSamplingPdf.
823/// The member _integrateBinsPrecision decides how we act:
824/// - < 0: Don't do anything.
825/// - = 0: Only enable feature if fitting unbinned PDF to RooDataHist.
826/// - > 0: Enable as requested.
829 return;
830
831 std::unique_ptr<RooArgSet> funcObservables( _funcClone->getObservables(*_dataClone) );
832 const bool oneDimAndBinned = (1 == std::count_if(funcObservables->begin(), funcObservables->end(), [](const RooAbsArg* arg) {
833 auto var = dynamic_cast<const RooRealVar*>(arg);
834 return var && var->numBins() > 1;
835 }));
836
837 if (!oneDimAndBinned) {
838 if (_integrateBinsPrecision > 0.) {
839 coutE(Fitting) << "Integration over bins was requested, but this is currently only implemented for 1-D fits." << std::endl;
840 }
841 return;
842 }
843
844 // Find the real-valued observable. We don't care about categories.
845 auto theObs = std::find_if(funcObservables->begin(), funcObservables->end(), [](const RooAbsArg* arg){
846 return dynamic_cast<const RooAbsRealLValue*>(arg);
847 });
848 assert(theObs != funcObservables->end());
849
850 RooBinSamplingPdf* newPdf = nullptr;
851
852 if (_integrateBinsPrecision > 0.) {
853 // User forced integration. Let just apply it.
854 newPdf = new RooBinSamplingPdf((std::string(_funcClone->GetName()) + "_binSampling").c_str(),
856 *static_cast<RooAbsRealLValue*>(*theObs),
857 *static_cast<RooAbsPdf*>(_funcClone),
859 } else if (dynamic_cast<RooDataHist*>(_dataClone) != nullptr
862 // User didn't forbid integration, and it seems appropriate with a RooDataHist.
863 coutI(Fitting) << "The PDF '" << _funcClone->GetName() << "' is continuous, but fit to binned data.\n"
864 << "RooFit will integrate it in each bin using the RooBinSamplingPdf." << std::endl;
865 newPdf = new RooBinSamplingPdf((std::string(_funcClone->GetName()) + "_binSampling").c_str(),
867 *static_cast<RooAbsRealLValue*>(*theObs),
868 *static_cast<RooAbsPdf*>(_funcClone));
869 }
870
871 if (newPdf) {
873 _funcClone = newPdf;
874 }
875}
#define e(i)
Definition: RSha256.hxx:103
#define coutI(a)
Definition: RooMsgService.h:30
#define cxcoutI(a)
Definition: RooMsgService.h:85
#define coutW(a)
Definition: RooMsgService.h:32
#define cxcoutW(a)
Definition: RooMsgService.h:93
#define coutE(a)
Definition: RooMsgService.h:33
int Int_t
Definition: RtypesCore.h:45
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
double Double_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition: TGX11.cxx:110
char * Form(const char *fmt,...)
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition: RooAbsArg.h:72
virtual RooAbsArg * cloneTree(const char *newname=0) const
Clone tree expression of objects.
Definition: RooAbsArg.cxx:2232
RooArgSet * getObservables(const RooArgSet &set, Bool_t valueOnly=kTRUE) const
Given a set of possible observables, return the observables that this PDF depends on.
Definition: RooAbsArg.h:295
void printCompactTree(const char *indent="", const char *fileName=0, const char *namePat=0, RooAbsArg *client=0)
Print tree structure of expression tree on stdout, or to file if filename is specified.
Definition: RooAbsArg.cxx:1846
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:323
Bool_t findConstantNodes(const RooArgSet &observables, RooArgSet &cacheList)
Find branch nodes with all-constant parameters, and add them to the list of nodes that can be cached ...
Definition: RooAbsArg.cxx:1713
friend class RooArgSet
Definition: RooAbsArg.h:600
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:336
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:291
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition: RooAbsArg.h:491
Bool_t addOwnedComponents(const RooArgSet &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2218
virtual void optimizeCacheMode(const RooArgSet &observables)
Activate cache mode optimization with given definition of observables.
Definition: RooAbsArg.cxx:1637
@ DeActivate
Definition: RooAbsArg.h:389
@ ValueChange
Definition: RooAbsArg.h:389
@ ConfigChange
Definition: RooAbsArg.h:389
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:314
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...
Definition: RooAbsArg.cxx:578
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=0, Bool_t recurseNonDerived=kFALSE) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
Definition: RooAbsArg.cxx:520
Bool_t recursiveRedirectServers(const RooAbsCollection &newServerList, Bool_t mustReplaceAll=kFALSE, Bool_t nameChange=kFALSE, Bool_t recurseInNewSet=kTRUE)
Recursively replace all servers with the new servers in newSet.
Definition: RooAbsArg.cxx:1159
virtual RooAbsReal * highBoundFunc() const
Return pointer to RooAbsReal parameterized upper bound, if any.
Definition: RooAbsBinning.h:88
virtual RooAbsReal * lowBoundFunc() const
Return pointer to RooAbsReal parameterized lower bound, if any.
Definition: RooAbsBinning.h:84
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
Int_t getSize() const
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * first() const
void setAttribAll(const Text_t *name, Bool_t value=kTRUE)
Set given attribute in each element of the collection by calling each elements setAttribute() functio...
bool selectCommon(const RooAbsCollection &refColl, RooAbsCollection &outColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
RooAbsCollection * selectByAttrib(const char *name, Bool_t value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
RooAbsArg * find(const char *name) const
Find object with given name in list.
virtual const RooAbsArg * cacheOwner()=0
virtual void forceCacheUpdate()
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:79
virtual const RooArgSet * get() const
Definition: RooAbsData.h:125
RooAbsDataStore * store()
Definition: RooAbsData.h:101
virtual void optimizeReadingWithCaching(RooAbsArg &arg, const RooArgSet &cacheList, const RooArgSet &keepObsList)
Prepare dataset for use with cached constant terms listed in 'cacheList' of expression 'arg'.
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Definition: RooAbsData.cxx:376
RooArgSet const * getGlobalObservables() const
Returns snapshot of global observables stored in this data.
Definition: RooAbsData.h:310
virtual void resetCache()
Internal method – Remove cached function values.
Definition: RooAbsData.cxx:407
Bool_t hasFilledCache() const
RooAbsData * reduce(const RooCmdArg &arg1, const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg(), const RooCmdArg &arg7=RooCmdArg(), const RooCmdArg &arg8=RooCmdArg())
Create a reduced copy of this dataset.
Definition: RooAbsData.cxx:451
virtual void cacheArgs(const RooAbsArg *owner, RooArgSet &varSet, const RooArgSet *nset=0, Bool_t skipZeroWeights=kFALSE)
Internal method – Cache given set of functions with data.
Definition: RooAbsData.cxx:399
void attachBuffers(const RooArgSet &extObs)
virtual void setArgStatus(const RooArgSet &set, Bool_t active)
Definition: RooAbsData.cxx:423
void setDirtyProp(Bool_t flag)
Control propagation of dirty flags from observables in dataset.
Definition: RooAbsData.cxx:431
RooAbsOptTestStatistic is the abstract base class for test statistics objects that evaluate a functio...
virtual ~RooAbsOptTestStatistic()
Destructor.
RooAbsReal * _origFunc
List of nodes that are cached as constant expressions.
void optimizeCaching()
This method changes the value caching logic for all nodes that depends on any of the observables as d...
const char * sealNotice() const
void optimizeConstantTerms(Bool_t, Bool_t=kTRUE)
Driver function to activate global constant term optimization.
void setUpBinSampling()
Inspect PDF to find out if we are doing a binned fit to a 1-dimensional unbinned PDF.
virtual Bool_t allowFunctionCache()
virtual Bool_t redirectServersHook(const RooAbsCollection &newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
Catch server redirect calls and forward to internal clone of function.
virtual void printCompactTreeHook(std::ostream &os, const char *indent="")
Catch print hook function and forward to function clone.
void initSlave(RooAbsReal &real, RooAbsData &indata, const RooArgSet &projDeps, const char *rangeName, const char *addCoefRangeName)
virtual Double_t combinedValue(RooAbsReal **gofArray, Int_t nVal) const
Method to combined test statistic results calculated into partitions into the global result.
virtual RooArgSet requiredExtraObservables() const
RooAbsOptTestStatistic()
Default Constructor.
Bool_t setDataSlave(RooAbsData &data, Bool_t cloneData=kTRUE, Bool_t ownNewDataAnyway=kFALSE)
Change dataset that is used to given one.
void constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt=kTRUE)
Driver function to propagate constant term optimizations in test statistic.
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
virtual Double_t getMax(const char *name=0) const
Get maximum of currently defined range.
virtual Bool_t hasRange(const char *name) const
Check if variable has a binning with given name.
virtual Double_t getMin(const char *name=0) const
Get miniminum of currently defined range.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:61
virtual void fixAddCoefRange(const char *rangeName=0, Bool_t force=kTRUE)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:91
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
Definition: RooAbsReal.h:341
virtual Double_t getValV(const RooArgSet *normalisationSet=nullptr) const
Return value of object.
Definition: RooAbsReal.cxx:275
virtual void fixAddCoefNormalization(const RooArgSet &addNormSet=RooArgSet(), Bool_t force=kTRUE)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
RooAbsTestStatistic is the abstract base class for all test statistics.
GOFOpMode operMode() const
virtual void constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt=kTRUE)
Forward constant term optimization management calls to component test statistics.
virtual Bool_t redirectServersHook(const RooAbsCollection &newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
Forward server redirect calls to component test statistics.
void setEventCount(Int_t nEvents)
virtual Double_t getCarry() const
Double_t _evalCarry
Offset as KahanSum to avoid loss of precision.
const bool _takeGlobalObservablesFromData
virtual void printCompactTreeHook(std::ostream &os, const char *indent="")
Add extra information on component test statistics when printing itself as part of a tree structure.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:35
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition: RooArgSet.h:154
The RooBinSamplingPdf is supposed to be used as an adapter between a continuous PDF and a binned dist...
The RooDataHist is a container class to hold N-dimensional binned data.
Definition: RooDataHist.h:44
void cacheValidEntries()
Compute which bins of the dataset are part of the currently set fit range.
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:36
static void softAbort()
RooProdPdf is an efficient implementation of a product of PDFs of the form.
Definition: RooProdPdf.h:37
RooArgSet * getConnectedParameters(const RooArgSet &observables) const
Return all parameter constraint p.d.f.s on parameters listed in constrainedParams.
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:39
void setRange(const char *name, Double_t min, Double_t max)
Set a fit or plotting range.
Definition: RooRealVar.cxx:526
const RooAbsBinning & getBinning(const char *name=0, Bool_t verbose=kTRUE, Bool_t createOnTheFly=kFALSE) const
Return binning definition with name.
Definition: RooRealVar.cxx:318
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE) override
Overloaded RooArgSet::add() method inserts 'var' into set and registers 'var' as server to owner with...
virtual void removeAll() override
Remove all argument inset using remove(const RooAbsArg&).
RooVectorDataStore uses std::vectors to store data columns.
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Basic string class.
Definition: TString.h:136
const char * Data() const
Definition: TString.h:369
RooCmdArg SelectVars(const RooArgSet &vars)
RooCmdArg CutRange(const char *rangeName)
Double_t y[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
@ Minimization
Definition: RooGlobalFunc.h:60
@ Optimization
Definition: RooGlobalFunc.h:61
@ InputArguments
Definition: RooGlobalFunc.h:61
@ ObjectHandling
Definition: RooGlobalFunc.h:61
static uint64_t sum(uint64_t i)
Definition: Factory.cxx:2345