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 "TClass.h"
42#include <string.h>
43
44
46#include "RooMsgService.h"
47#include "RooAbsPdf.h"
48#include "RooAbsData.h"
49#include "RooDataHist.h"
50#include "RooArgSet.h"
51#include "RooRealVar.h"
52#include "RooErrorHandler.h"
53#include "RooGlobalFunc.h"
54#include "RooBinning.h"
55#include "RooAbsDataStore.h"
56#include "RooCategory.h"
57#include "RooDataSet.h"
58#include "RooProdPdf.h"
59#include "RooAddPdf.h"
60#include "RooProduct.h"
61#include "RooRealSumPdf.h"
62#include "RooTrace.h"
63#include "RooVectorDataStore.h"
64#include "RooBinSamplingPdf.h"
65
66using namespace std;
67
69;
70
71
72////////////////////////////////////////////////////////////////////////////////
73/// Default Constructor
74
76{
77 // Initialize all non-persisted data members
78
79 _funcObsSet = 0 ;
80 _funcCloneSet = 0 ;
81 _funcClone = 0 ;
82
83 _normSet = 0 ;
84 _projDeps = 0 ;
85
86 _origFunc = 0 ;
87 _origData = 0 ;
88
89 _ownData = kTRUE ;
90 _sealed = kFALSE ;
92}
93
94
95
96////////////////////////////////////////////////////////////////////////////////
97/// Create a test statistic, and optimise its calculation.
98/// \param[in] name Name of the instance.
99/// \param[in] title Title (for e.g. plotting).
100/// \param[in] real Function to evaluate.
101/// \param[in] indata Dataset for which to compute test statistic.
102/// \param[in] projDeps A set of projected observables.
103/// \param[in] rangeName If not null, only events in the dataset inside the range will be used in the test
104/// statistic calculation.
105/// \param[in] addCoefRangeName If not null, all RooAddPdf components of `real` will be
106/// instructed to fix their fraction definitions to the given named range.
107/// \param[in] nCPU If > 1, the test statistic calculation will be parallelised over multiple processes. By default, the data
108/// is split with 'bulk' partitioning (each process calculates a contiguous block of fraction 1/nCPU
109/// of the data). For binned data, this approach may be suboptimal as the number of bins with >0 entries
110/// in each processing block may vary greatly; thereby distributing the workload rather unevenly.
111/// \param[in] interleave Strategy how to distribute events among workers. If an interleave partitioning strategy is used where each partition
112/// i takes all bins for which (ibin % ncpu == i), an even distribution of work is more likely.
113/// \param[in] splitCutRange If true, a different rangeName constructed as `rangeName_{catName}` will be used
114/// as range definition for each index state of a RooSimultaneous.
115/// \param[in] cloneInputData Not used. Data is always cloned.
116/// \param[in] integrateOverBinsPrecision If > 0, PDF in binned fits are integrated over the bins. This sets the precision. If = 0,
117/// only unbinned PDFs fit to RooDataHist are integrated. If < 0, PDFs are never integrated.
119 RooAbsData& indata, const RooArgSet& projDeps,
121 RooAbsTestStatistic(name,title,real,indata,projDeps,cfg),
122 _projDeps(0),
123 _sealed(kFALSE),
124 _optimized(kFALSE),
125 _integrateBinsPrecision(cfg.integrateOverBinsPrecision)
126{
127 // Don't do a thing in master mode
128
129 if (operMode()!=Slave) {
130 _funcObsSet = 0 ;
131 _funcCloneSet = 0 ;
132 _funcClone = 0 ;
133 _normSet = 0 ;
134 _projDeps = 0 ;
135 _origFunc = 0 ;
136 _origData = 0 ;
137 _ownData = kFALSE ;
138 _sealed = kFALSE ;
139 return ;
140 }
141
142 _origFunc = 0 ; //other._origFunc ;
143 _origData = 0 ; // other._origData ;
144
145 initSlave(real, indata, projDeps, _rangeName.c_str(), _addCoefRangeName.c_str()) ;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Copy constructor
150
152 RooAbsTestStatistic(other,name), _sealed(other._sealed), _sealNotice(other._sealNotice), _optimized(kFALSE),
153 _integrateBinsPrecision(other._integrateBinsPrecision)
154{
155 // Don't do a thing in master mode
156 if (operMode()!=Slave) {
157
158 _funcObsSet = 0 ;
159 _funcCloneSet = 0 ;
160 _funcClone = 0 ;
161 _normSet = other._normSet ? ((RooArgSet*) other._normSet->snapshot()) : 0 ;
162 _projDeps = 0 ;
163 _origFunc = 0 ;
164 _origData = 0 ;
165 _ownData = kFALSE ;
166 return ;
167 }
168
169 _origFunc = 0 ; //other._origFunc ;
170 _origData = 0 ; // other._origData ;
171 _projDeps = 0 ;
172
173 initSlave(*other._funcClone,*other._dataClone,other._projDeps?*other._projDeps:RooArgSet(),other._rangeName.c_str(),other._addCoefRangeName.c_str()) ;
174}
175
176
177
178////////////////////////////////////////////////////////////////////////////////
179
180void RooAbsOptTestStatistic::initSlave(RooAbsReal& real, RooAbsData& indata, const RooArgSet& projDeps, const char* rangeName,
181 const char* addCoefRangeName) {
182 // ******************************************************************
183 // *** PART 1 *** Clone incoming pdf, attach to each other *
184 // ******************************************************************
185
186 // Clone FUNC
187 _funcClone = static_cast<RooAbsReal*>(real.cloneTree());
188 _funcCloneSet = 0 ;
189
190 // Attach FUNC to data set
192
193 if (_funcClone->getAttribute("BinnedLikelihood")) {
194 _funcClone->setAttribute("BinnedLikelihoodActive") ;
195 }
196
197 // Reattach FUNC to original parameters
198 RooArgSet* origParams = (RooArgSet*) real.getParameters(indata) ;
200
201 // Mark all projected dependents as such
202 if (projDeps.getSize()>0) {
203 RooArgSet *projDataDeps = (RooArgSet*) _funcObsSet->selectCommon(projDeps) ;
204 projDataDeps->setAttribAll("projectedDependent") ;
205 delete projDataDeps ;
206 }
207
208 // If PDF is a RooProdPdf (with possible constraint terms)
209 // analyze pdf for actual parameters (i.e those in unconnected constraint terms should be
210 // ignored as here so that the test statistic will not be recalculated if those
211 // are changed
212 RooProdPdf* pdfWithCons = dynamic_cast<RooProdPdf*>(_funcClone) ;
213 if (pdfWithCons) {
214
215 RooArgSet* connPars = pdfWithCons->getConnectedParameters(*indata.get()) ;
216 // Add connected parameters as servers
218 _paramSet.add(*connPars) ;
219 delete connPars ;
220
221 } else {
222 // Add parameters as servers
223 _paramSet.add(*origParams) ;
224 }
225
226
227 delete origParams ;
228
229 // Store normalization set
230 _normSet = (RooArgSet*) indata.get()->snapshot(kFALSE) ;
231
232 // Expand list of observables with any observables used in parameterized ranges.
233 // This NEEDS to be a counting loop since we are inserting during the loop.
234 for (std::size_t i = 0; i < _funcObsSet->size(); ++i) {
235 auto realDepRLV = dynamic_cast<const RooAbsRealLValue*>((*_funcObsSet)[i]);
236 if (realDepRLV && realDepRLV->isDerived()) {
237 RooArgSet tmp2;
238 realDepRLV->leafNodeServerList(&tmp2, 0, kTRUE);
239 _funcObsSet->add(tmp2,kTRUE);
240 }
241 }
242
243
244
245 // ******************************************************************
246 // *** PART 2 *** Clone and adjust incoming data, attach to PDF *
247 // ******************************************************************
248
249 // Check if the fit ranges of the dependents in the data and in the FUNC are consistent
250 const RooArgSet* dataDepSet = indata.get() ;
251 for (const auto arg : *_funcObsSet) {
252
253 // Check that both dataset and function argument are of type RooRealVar
254 RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
255 if (!realReal) continue ;
256 RooRealVar* datReal = dynamic_cast<RooRealVar*>(dataDepSet->find(realReal->GetName())) ;
257 if (!datReal) continue ;
258
259 // Check that range of observables in pdf is equal or contained in range of observables in data
260
261 if (!realReal->getBinning().lowBoundFunc() && realReal->getMin()<(datReal->getMin()-1e-6)) {
262 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR minimum of FUNC observable " << arg->GetName()
263 << "(" << realReal->getMin() << ") is smaller than that of "
264 << arg->GetName() << " in the dataset (" << datReal->getMin() << ")" << endl ;
266 return ;
267 }
268
269 if (!realReal->getBinning().highBoundFunc() && realReal->getMax()>(datReal->getMax()+1e-6)) {
270 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR maximum of FUNC observable " << arg->GetName()
271 << " is larger than that of " << arg->GetName() << " in the dataset" << endl ;
273 return ;
274 }
275 }
276
277 // Copy data and strip entries lost by adjusted fit range, _dataClone ranges will be copied from realDepSet ranges
278 if (rangeName && strlen(rangeName)) {
280 // cout << "RooAbsOptTestStatistic: reducing dataset to fit in range named " << rangeName << " resulting dataset has " << _dataClone->sumEntries() << " events" << endl ;
281 } else {
282 _dataClone = (RooAbsData*) indata.Clone() ;
283 }
284 _ownData = kTRUE ;
285
286
287 // ******************************************************************
288 // *** PART 3 *** Make adjustments for fit ranges, if specified *
289 // ******************************************************************
290
291 std::unique_ptr<RooArgSet> origObsSet( real.getObservables(indata) );
292 RooArgSet* dataObsSet = (RooArgSet*) _dataClone->get() ;
293 if (rangeName && strlen(rangeName)) {
294 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") constructing test statistic for sub-range named " << rangeName << endl ;
295
296 bool observablesKnowRange = false;
297 // Adjust FUNC normalization ranges to requested fitRange, store original ranges for RooAddPdf coefficient interpretation
298 for (const auto arg : *_funcObsSet) {
299
300 RooRealVar* realObs = dynamic_cast<RooRealVar*>(arg) ;
301 if (realObs) {
302
303 observablesKnowRange |= realObs->hasRange(rangeName);
304
305 // If no explicit range is given for RooAddPdf coefficients, create explicit named range equivalent to original observables range
306 if (!(addCoefRangeName && strlen(addCoefRangeName))) {
307 realObs->setRange(Form("NormalizationRangeFor%s",rangeName),realObs->getMin(),realObs->getMax()) ;
308 }
309
310 // Adjust range of function observable to those of given named range
311 realObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ;
312
313 // Adjust range of data observable to those of given named range
314 RooRealVar* dataObs = (RooRealVar*) dataObsSet->find(realObs->GetName()) ;
315 dataObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ;
316
317 // Keep track of list of fit ranges in string attribute fit range of original p.d.f.
318 if (!_splitRange) {
319 const std::string fitRangeName = std::string("fit_") + GetName();
320 const char* origAttrib = real.getStringAttribute("fitrange") ;
321 std::string newAttr = origAttrib ? origAttrib : "";
322
323 if (newAttr.find(fitRangeName) == std::string::npos) {
324 newAttr += (newAttr.empty() ? "" : ",") + fitRangeName;
325 }
326 real.setStringAttribute("fitrange", newAttr.c_str());
327 RooRealVar* origObs = (RooRealVar*) origObsSet->find(arg->GetName()) ;
328 if (origObs) {
329 origObs->setRange(fitRangeName.c_str(), realObs->getMin(rangeName), realObs->getMax(rangeName));
330 }
331 }
332 }
333 }
334
335 if (!observablesKnowRange)
336 coutW(Fitting) << "None of the fit observables seem to know the range '" << rangeName << "'. This means that the full range will be used." << std::endl;
337 }
338
339
340 // ******************************************************************
341 // *** PART 3.2 *** Binned fits *
342 // ******************************************************************
343
344 // If dataset is binned, activate caching of bins that are invalid because the're outside the
345 // updated range definition (WVE need to add virtual interface here)
346 RooDataHist* tmph = dynamic_cast<RooDataHist*>(_dataClone) ;
347 if (tmph) {
348 tmph->cacheValidEntries() ;
349 }
350
352
353
354 // Fix RooAddPdf coefficients to original normalization range
355 if (rangeName && strlen(rangeName)) {
356
357 // WVE Remove projected dependents from normalization
359
360 if (addCoefRangeName && strlen(addCoefRangeName)) {
361 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
362 << ") fixing interpretation of coefficients of any RooAddPdf component to range " << addCoefRangeName << endl ;
363 _funcClone->fixAddCoefRange(addCoefRangeName,kFALSE) ;
364 } else {
365 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
366 << ") fixing interpretation of coefficients of any RooAddPdf to full domain of observables " << endl ;
367 _funcClone->fixAddCoefRange(Form("NormalizationRangeFor%s",rangeName),kFALSE) ;
368 }
369 }
370
371
372 // This is deferred from part 2 - but must happen after part 3 - otherwise invalid bins cannot be properly marked in cacheValidEntries
375
376
377
378
379 // *********************************************************************
380 // *** PART 4 *** Adjust normalization range for projected observables *
381 // *********************************************************************
382
383 // Remove projected dependents from normalization set
384 if (projDeps.getSize()>0) {
385
386 _projDeps = (RooArgSet*) projDeps.snapshot(kFALSE) ;
387
388 //RooArgSet* tobedel = (RooArgSet*) _normSet->selectCommon(*_projDeps) ;
390
391 // Mark all projected dependents as such
393 projDataDeps->setAttribAll("projectedDependent") ;
394 delete projDataDeps ;
395 }
396
397
398 coutI(Optimization) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") optimizing internal clone of p.d.f for likelihood evaluation."
399 << "Lazy evaluation and associated change tracking will disabled for all nodes that depend on observables" << endl ;
400
401
402 // *********************************************************************
403 // *** PART 4 *** Finalization and activation of optimization *
404 // *********************************************************************
405
406 // Redirect pointers of base class to clone
407 _func = _funcClone ;
408 _data = _dataClone ;
409
411
413
414 // It would be unusual if the global observables are used in the likelihood
415 // outside of the constraint terms, but if they are we have to be consistent
416 // and also redirect them to the snapshots in the dataset if appropriate.
419 }
420
421}
422
423
424////////////////////////////////////////////////////////////////////////////////
425/// Destructor
426
428{
429 if (operMode()==Slave) {
430 delete _funcClone ;
431 delete _funcObsSet ;
432 if (_projDeps) {
433 delete _projDeps ;
434 }
435 if (_ownData) {
436 delete _dataClone ;
437 }
438 }
439 delete _normSet ;
440}
441
442
443
444////////////////////////////////////////////////////////////////////////////////
445/// Method to combined test statistic results calculated into partitions into
446/// the global result. This default implementation adds the partition return
447/// values
448
450{
451 // Default implementation returns sum of components
452 Double_t sum(0), carry(0);
453 for (Int_t i = 0; i < n; ++i) {
454 Double_t y = array[i]->getValV();
455 carry += reinterpret_cast<RooAbsOptTestStatistic*>(array[i])->getCarry();
456 y -= carry;
457 const Double_t t = sum + y;
458 carry = (t - sum) - y;
459 sum = t;
460 }
461 _evalCarry = carry;
462 return sum ;
463}
464
465
466
467////////////////////////////////////////////////////////////////////////////////
468/// Catch server redirect calls and forward to internal clone of function
469
470Bool_t RooAbsOptTestStatistic::redirectServersHook(const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
471{
472 RooAbsTestStatistic::redirectServersHook(newServerList,mustReplaceAll,nameChange,isRecursive) ;
473 if (operMode()!=Slave) return kFALSE ;
474 Bool_t ret = _funcClone->recursiveRedirectServers(newServerList,kFALSE,nameChange) ;
475 return ret ;
476}
477
478
479
480////////////////////////////////////////////////////////////////////////////////
481/// Catch print hook function and forward to function clone
482
484{
486 if (operMode()!=Slave) return ;
487 TString indent2(indent) ;
488 indent2 += "opt >>" ;
489 _funcClone->printCompactTree(os,indent2.Data()) ;
490 os << indent2 << " dataset clone = " << _dataClone << " first obs = " << _dataClone->get()->first() << endl ;
491}
492
493
494
495////////////////////////////////////////////////////////////////////////////////
496/// Driver function to propagate constant term optimizations in test statistic.
497/// If code Activate is sent, constant term optimization will be executed.
498/// If code Deactivate is sent, any existing constant term optimizations will
499/// be abandoned. If codes ConfigChange or ValueChange are sent, any existing
500/// constant term optimizations will be redone.
501
503{
504 // cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump BEFORE const-opt" << endl ;
505 // _funcClone->Print("t") ;
506
507 RooAbsTestStatistic::constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
508 if (operMode()!=Slave) return ;
509
510 if (_dataClone->hasFilledCache() && _dataClone->store()->cacheOwner()!=this) {
511 if (opcode==Activate) {
512 cxcoutW(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
513 << ") dataset cache is owned by another object, no constant term optimization can be applied" << endl ;
514 }
515 return ;
516 }
517
518 if (!allowFunctionCache()) {
519 if (opcode==Activate) {
520 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
521 << ") function caching prohibited by test statistic, no constant term optimization is applied" << endl ;
522 }
523 return ;
524 }
525
526 if (_dataClone->hasFilledCache() && opcode==Activate) {
527 opcode=ValueChange ;
528 }
529
530 switch(opcode) {
531 case Activate:
532 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
533 << ") optimizing evaluation of test statistic by finding all nodes in p.d.f that depend exclusively"
534 << " on observables and constant parameters and precalculating their values" << endl ;
535 optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
536 break ;
537
538 case DeActivate:
539 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
540 << ") deactivating optimization of constant terms in test statistic" << endl ;
542 break ;
543
544 case ConfigChange:
545 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
546 << ") one ore more parameter were changed from constant to floating or vice versa, "
547 << "re-evaluating constant term optimization" << endl ;
549 optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
550 break ;
551
552 case ValueChange:
553 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
554 << ") the value of one ore more constant parameter were changed re-evaluating constant term optimization" << endl ;
555 // Request a forcible cache update of all cached nodes
557
558 break ;
559 }
560
561// cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump AFTER const-opt" << endl ;
562// _funcClone->Print("t") ;
563}
564
565
566
567////////////////////////////////////////////////////////////////////////////////
568/// This method changes the value caching logic for all nodes that depends on any of the observables
569/// as defined by the given dataset. When evaluating a test statistic constructed from the RooAbsReal
570/// with a dataset the observables are guaranteed to change with every call, thus there is no point
571/// in tracking these changes which result in a net overhead. Thus for observable-dependent nodes,
572/// the evaluation mechanism is changed from being dependent on a 'valueDirty' flag to guaranteed evaluation.
573/// On the dataset side, the observables objects are modified to no longer send valueDirty messages
574/// to their client
575
577{
578// cout << "RooAbsOptTestStatistic::optimizeCaching(" << GetName() << "," << this << ")" << endl ;
579
580 // Trigger create of all object caches now in nodes that have deferred object creation
581 // so that cache contents can be processed immediately
583
584 // Set value caching mode for all nodes that depend on any of the observables to ADirty
586
587 // Disable propagation of dirty state flags for observables
589
590 // Disable reading of observables that are not used
592}
593
594
595
596////////////////////////////////////////////////////////////////////////////////
597/// Driver function to activate global constant term optimization.
598/// If activated, constant terms are found and cached with the dataset.
599/// The operation mode of cached nodes is set to AClean meaning that
600/// their getVal() call will never result in an evaluate call.
601/// Finally the branches in the dataset that correspond to observables
602/// that are exclusively used in constant terms are disabled as
603/// they serve no more purpose
604
606{
607 if(activate) {
608
609 if (_optimized) {
610 return ;
611 }
612
613 // Trigger create of all object caches now in nodes that have deferred object creation
614 // so that cache contents can be processed immediately
616
617
618 // WVE - Patch to allow customization of optimization level per component pdf
619 if (_funcClone->getAttribute("NoOptimizeLevel1")) {
620 coutI(Minimization) << " Optimization customization: Level-1 constant-term optimization prohibited by attribute NoOptimizeLevel1 set on top-level pdf "
621 << _funcClone->IsA()->GetName() << "::" << _funcClone->GetName() << endl ;
622 return ;
623 }
624 if (_funcClone->getAttribute("NoOptimizeLevel2")) {
625 coutI(Minimization) << " Optimization customization: Level-2 constant-term optimization prohibited by attribute NoOptimizeLevel2 set on top-level pdf "
626 << _funcClone->IsA()->GetName() << "::" << _funcClone->GetName() << endl ;
627 applyTrackingOpt=kFALSE ;
628 }
629
630 // Apply tracking optimization here. Default strategy is to track components
631 // of RooAddPdfs and RooRealSumPdfs. If these components are a RooProdPdf
632 // or a RooProduct respectively, track the components of these products instead
633 // of the product term
634 RooArgSet trackNodes ;
635
636
637 // Add safety check here - applyTrackingOpt will only be applied if present
638 // dataset is constructed in terms of a RooVectorDataStore
639 if (applyTrackingOpt) {
640 if (!dynamic_cast<RooVectorDataStore*>(_dataClone->store())) {
641 coutW(Optimization) << "RooAbsOptTestStatistic::optimizeConstantTerms(" << GetName()
642 << ") WARNING Cache-and-track optimization (Optimize level 2) is only available for datasets"
643 << " implement in terms of RooVectorDataStore - ignoring this option for current dataset" << endl ;
644 applyTrackingOpt = kFALSE ;
645 }
646 }
647
648 if (applyTrackingOpt) {
649 RooArgSet branches ;
650 _funcClone->branchNodeServerList(&branches) ;
651 for (auto arg : branches) {
652 arg->setCacheAndTrackHints(trackNodes);
653 }
654 // Do not set CacheAndTrack on constant expressions
655 RooArgSet* constNodes = (RooArgSet*) trackNodes.selectByAttrib("Constant",kTRUE) ;
656 trackNodes.remove(*constNodes) ;
657 delete constNodes ;
658
659 // Set CacheAndTrack flag on all remaining nodes
660 trackNodes.setAttribAll("CacheAndTrack",kTRUE) ;
661 }
662
663 // Find all nodes that depend exclusively on constant parameters
665
667
668 // Cache constant nodes with dataset - also cache entries corresponding to zero-weights in data when using BinnedLikelihood
669 _dataClone->cacheArgs(this,_cachedNodes,_normSet,!_funcClone->getAttribute("BinnedLikelihood")) ;
670
671 // Put all cached nodes in AClean value caching mode so that their evaluate() is never called
672 for (auto cacheArg : _cachedNodes) {
673 cacheArg->setOperMode(RooAbsArg::AClean) ;
674 }
675
676 RooArgSet* constNodes = (RooArgSet*) _cachedNodes.selectByAttrib("ConstantExpressionCached",kTRUE) ;
677 RooArgSet actualTrackNodes(_cachedNodes) ;
678 actualTrackNodes.remove(*constNodes) ;
679 if (constNodes->getSize()>0) {
680 if (constNodes->getSize()<20) {
681 coutI(Minimization) << " The following expressions have been identified as constant and will be precalculated and cached: " << *constNodes << endl ;
682 } else {
683 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions have been identified as constant and will be precalculated and cached." << endl ;
684 }
685 }
686 if (actualTrackNodes.getSize()>0) {
687 if (actualTrackNodes.getSize()<20) {
688 coutI(Minimization) << " The following expressions will be evaluated in cache-and-track mode: " << actualTrackNodes << endl ;
689 } else {
690 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions will be evaluated in cache-and-track-mode." << endl ;
691 }
692 }
693 delete constNodes ;
694
695 // Disable reading of observables that are no longer used
697
698 _optimized = kTRUE ;
699
700 } else {
701
702 // Delete the cache
704
705 // Reactivate all tree branches
707
708 // Reset all nodes to ADirty
710
711 // Disable propagation of dirty state flags for observables
713
715
716
718 }
719}
720
721
722
723////////////////////////////////////////////////////////////////////////////////
724/// Change dataset that is used to given one. If cloneData is kTRUE, a clone of
725/// in the input dataset is made. If the test statistic was constructed with
726/// a range specification on the data, the cloneData argument is ignored and
727/// the data is always cloned.
729{
730
731 if (operMode()==SimMaster) {
732 //cout << "ROATS::setDataSlave() ERROR this is SimMaster _funcClone = " << _funcClone << endl ;
733 return kFALSE ;
734 }
735
736 //cout << "ROATS::setDataSlave() new dataset size = " << indata.numEntries() << endl ;
737 //indata.Print("v") ;
738
739
740 // If the current dataset is owned, transfer the ownership to unique pointer
741 // that will get out of scope at the end of this function. We can't delete it
742 // right now, because there might be global observables in the model that
743 // first need to be redirected to the new dataset with a later call to
744 // RooAbsArg::recursiveRedirectServers.
745 std::unique_ptr<RooAbsData> oldOwnedData;
746 if (_ownData) {
747 oldOwnedData.reset(_dataClone);
748 _dataClone = nullptr ;
749 }
750
751 if (!cloneData && _rangeName.size()>0) {
752 coutW(InputArguments) << "RooAbsOptTestStatistic::setData(" << GetName() << ") WARNING: test statistic was constructed with range selection on data, "
753 << "ignoring request to _not_ clone the input dataset" << endl ;
754 cloneData = kTRUE ;
755 }
756
757 if (cloneData) {
758 // Cloning input dataset
759 if (_rangeName.size()==0) {
760 _dataClone = (RooAbsData*) indata.reduce(*indata.get()) ;
761 } else {
763 }
764 _ownData = kTRUE ;
765
766 } else {
767
768 // Taking input dataset
769 _dataClone = &indata ;
770 _ownData = ownNewData ;
771
772 }
773
774 // Attach function clone to dataset
777 _data = _dataClone ;
778
779 // ReCache constant nodes with dataset
780 if (_cachedNodes.getSize()>0) {
782 }
783
784 // Adjust internal event count
785 setEventCount(indata.numEntries()) ;
786
787 setValueDirty() ;
788
789 // It would be unusual if the global observables are used in the likelihood
790 // outside of the constraint terms, but if they are we have to be consistent
791 // and also redirect them to the snapshots in the dataset if appropriate.
794 }
795
796 return kTRUE ;
797}
798
799
800
801
802////////////////////////////////////////////////////////////////////////////////
803
805{
806 if (_sealed) {
807 Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
808 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
809 << ") WARNING: object sealed by creator - access to data is not permitted: "
810 << (notice?sealNotice():"<no user notice>") << endl ;
811 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
812 return dummy ;
813 }
814 return *_dataClone ;
815}
816
817
818////////////////////////////////////////////////////////////////////////////////
819
821{
822 if (_sealed) {
823 Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
824 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
825 << ") WARNING: object sealed by creator - access to data is not permitted: "
826 << (notice?sealNotice():"<no user notice>") << endl ;
827 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
828 return dummy ;
829 }
830 return *_dataClone ;
831}
832
833
834////////////////////////////////////////////////////////////////////////////////
835/// Inspect PDF to find out if we are doing a binned fit to a 1-dimensional unbinned PDF.
836/// If this is the case, enable finer sampling of bins by wrapping PDF into a RooBinSamplingPdf.
837/// The member _integrateBinsPrecision decides how we act:
838/// - < 0: Don't do anything.
839/// - = 0: Only enable feature if fitting unbinned PDF to RooDataHist.
840/// - > 0: Enable as requested.
842
843 auto& pdf = static_cast<RooAbsPdf&>(*_funcClone);
846 _funcClone = newPdf.release();
847 }
848
849}
#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
const Bool_t kFALSE
Definition: RtypesCore.h:101
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,...)
virtual RooAbsArg * cloneTree(const char *newname=0) const
Clone tree expression of objects.
Definition: RooAbsArg.cxx:2304
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:315
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:1897
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:316
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:1764
friend class RooArgSet
Definition: RooAbsArg.h:644
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2269
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:329
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:284
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition: RooAbsArg.h:511
virtual void optimizeCacheMode(const RooArgSet &observables)
Activate cache mode optimization with given definition of observables.
Definition: RooAbsArg.cxx:1688
@ DeActivate
Definition: RooAbsArg.h:409
@ ValueChange
Definition: RooAbsArg.h:409
@ ConfigChange
Definition: RooAbsArg.h:409
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:307
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:571
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:513
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:1194
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:81
virtual const RooArgSet * get() const
Definition: RooAbsData.h:127
RooAbsDataStore * store()
Definition: RooAbsData.h:103
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:381
RooArgSet const * getGlobalObservables() const
Returns snapshot of global observables stored in this data.
Definition: RooAbsData.h:312
virtual void resetCache()
Internal method – Remove cached function values.
Definition: RooAbsData.cxx:412
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:456
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:404
void attachBuffers(const RooArgSet &extObs)
virtual void setArgStatus(const RooArgSet &set, Bool_t active)
Definition: RooAbsData.cxx:428
void setDirtyProp(Bool_t flag)
Control propagation of dirty flags from observables in dataset.
Definition: RooAbsData.cxx:436
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:63
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:93
virtual Double_t getValV(const RooArgSet *normalisationSet=nullptr) const
Return value of object.
Definition: RooAbsReal.cxx:276
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:158
static std::unique_ptr< RooAbsPdf > create(RooAbsPdf &pdf, RooAbsData const &data, double precision)
Creates a wrapping RooBinSamplingPdf if appropriate.
The RooDataHist is a container class to hold N-dimensional binned data.
Definition: RooDataHist.h:45
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:33
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:551
const RooAbsBinning & getBinning(const char *name=0, Bool_t verbose=kTRUE, Bool_t createOnTheFly=kFALSE) const
Return binning definition with name.
Definition: RooRealVar.cxx:343
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 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