Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "Riostream.h"
39#include "TClass.h"
40#include <string.h>
41
42
44#include "RooMsgService.h"
45#include "RooAbsPdf.h"
46#include "RooAbsData.h"
47#include "RooDataHist.h"
48#include "RooArgSet.h"
49#include "RooRealVar.h"
50#include "RooErrorHandler.h"
51#include "RooGlobalFunc.h"
52#include "RooBinning.h"
53#include "RooAbsDataStore.h"
54#include "RooCategory.h"
55#include "RooDataSet.h"
56#include "RooProdPdf.h"
57#include "RooAddPdf.h"
58#include "RooProduct.h"
59#include "RooRealSumPdf.h"
60#include "RooTrace.h"
61#include "RooVectorDataStore.h"
62#include "RooBinSamplingPdf.h"
63
64#include "ROOT/StringUtils.hxx"
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 = true ;
90 _sealed = false ;
91 _optimized = false ;
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] cfg the statistic configuration
104///
105/// cfg contains:
106/// - rangeName If not null, only events in the dataset inside the range will be used in the test
107/// statistic calculation.
108/// - addCoefRangeName If not null, all RooAddPdf components of `real` will be
109/// instructed to fix their fraction definitions to the given named range.
110/// - nCPU If > 1, the test statistic calculation will be parallelised over multiple processes. By default, the data
111/// is split with 'bulk' partitioning (each process calculates a contiguous block of fraction 1/nCPU
112/// of the data). For binned data, this approach may be suboptimal as the number of bins with >0 entries
113/// in each processing block may vary greatly; thereby distributing the workload rather unevenly.
114/// - interleave Strategy how to distribute events among workers. If an interleave partitioning strategy is used where each partition
115/// i takes all bins for which (ibin % ncpu == i), an even distribution of work is more likely.
116/// - splitCutRange If true, a different rangeName constructed as `rangeName_{catName}` will be used
117/// as range definition for each index state of a RooSimultaneous.
118/// - cloneInputData Not used. Data is always cloned.
119/// - integrateOverBinsPrecision If > 0, PDF in binned fits are integrated over the bins. This sets the precision. If = 0,
120/// only unbinned PDFs fit to RooDataHist are integrated. If < 0, PDFs are never integrated.
122 RooAbsData& indata, const RooArgSet& projDeps,
124 RooAbsTestStatistic(name,title,real,indata,projDeps,cfg),
125 _projDeps(0),
126 _sealed(false),
127 _optimized(false),
128 _integrateBinsPrecision(cfg.integrateOverBinsPrecision)
129{
130 // Don't do a thing in master mode
131
132 if (operMode()!=Slave) {
133 _funcObsSet = 0 ;
134 _funcCloneSet = 0 ;
135 _funcClone = 0 ;
136 _normSet = 0 ;
137 _projDeps = 0 ;
138 _origFunc = 0 ;
139 _origData = 0 ;
140 _ownData = false ;
141 _sealed = false ;
142 return ;
143 }
144
145 _origFunc = 0 ; //other._origFunc ;
146 _origData = 0 ; // other._origData ;
147
148 initSlave(real, indata, projDeps, _rangeName.c_str(), _addCoefRangeName.c_str()) ;
149}
150
151////////////////////////////////////////////////////////////////////////////////
152/// Copy constructor
153
155 RooAbsTestStatistic(other,name), _sealed(other._sealed), _sealNotice(other._sealNotice), _optimized(false),
156 _integrateBinsPrecision(other._integrateBinsPrecision)
157{
158 // Don't do a thing in master mode
159 if (operMode()!=Slave) {
160
161 _funcObsSet = 0 ;
162 _funcCloneSet = 0 ;
163 _funcClone = 0 ;
164 _normSet = nullptr;
165 if(other._normSet) {
166 _normSet = new RooArgSet;
167 other._normSet->snapshot(*_normSet);
168 }
169 _projDeps = 0 ;
170 _origFunc = 0 ;
171 _origData = 0 ;
172 _ownData = false ;
173 return ;
174 }
175
176 _origFunc = 0 ; //other._origFunc ;
177 _origData = 0 ; // other._origData ;
178 _projDeps = 0 ;
179
180 initSlave(*other._funcClone,*other._dataClone,other._projDeps?*other._projDeps:RooArgSet(),other._rangeName.c_str(),other._addCoefRangeName.c_str()) ;
181}
182
183
184
185////////////////////////////////////////////////////////////////////////////////
186
187void RooAbsOptTestStatistic::initSlave(RooAbsReal& real, RooAbsData& indata, const RooArgSet& projDeps, const char* rangeName,
188 const char* addCoefRangeName) {
189 // ******************************************************************
190 // *** PART 1 *** Clone incoming pdf, attach to each other *
191 // ******************************************************************
192
193 // Clone FUNC
194 _funcClone = RooHelpers::cloneTreeWithSameParameters(real, indata.get()).release();
195 _funcCloneSet = 0 ;
196
197 // Attach FUNC to data set
198 _funcObsSet = std::unique_ptr<RooArgSet>{_funcClone->getObservables(indata)}.release();
199
200 if (_funcClone->getAttribute("BinnedLikelihood")) {
201 _funcClone->setAttribute("BinnedLikelihoodActive") ;
202 }
203
204 // Mark all projected dependents as such
205 if (!projDeps.empty()) {
206 std::unique_ptr<RooArgSet> projDataDeps{static_cast<RooArgSet*>(_funcObsSet->selectCommon(projDeps))};
207 projDataDeps->setAttribAll("projectedDependent") ;
208 }
209
210 // If PDF is a RooProdPdf (with possible constraint terms)
211 // analyze pdf for actual parameters (i.e those in unconnected constraint terms should be
212 // ignored as here so that the test statistic will not be recalculated if those
213 // are changed
214 RooProdPdf* pdfWithCons = dynamic_cast<RooProdPdf*>(_funcClone) ;
215 if (pdfWithCons) {
216
217 std::unique_ptr<RooArgSet> connPars{pdfWithCons->getConnectedParameters(*indata.get())};
218 // Add connected parameters as servers
219 _paramSet.add(*connPars) ;
220
221 } else {
222 // Add parameters as servers
224 }
225
226 // Store normalization set
227 _normSet = new RooArgSet;
228 indata.get()->snapshot(*_normSet, false);
229
230 // Expand list of observables with any observables used in parameterized ranges.
231 // This NEEDS to be a counting loop since we are inserting during the loop.
232 for (std::size_t i = 0; i < _funcObsSet->size(); ++i) {
233 auto realDepRLV = dynamic_cast<const RooAbsRealLValue*>((*_funcObsSet)[i]);
234 if (realDepRLV && realDepRLV->isDerived()) {
235 RooArgSet tmp2;
236 realDepRLV->leafNodeServerList(&tmp2, 0, true);
237 _funcObsSet->add(tmp2,true);
238 }
239 }
240
241
242
243 // ******************************************************************
244 // *** PART 2 *** Clone and adjust incoming data, attach to PDF *
245 // ******************************************************************
246
247 // Check if the fit ranges of the dependents in the data and in the FUNC are consistent
248 const RooArgSet* dataDepSet = indata.get() ;
249 for (const auto arg : *_funcObsSet) {
250
251 // Check that both dataset and function argument are of type RooRealVar
252 RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
253 if (!realReal) continue ;
254 RooRealVar* datReal = dynamic_cast<RooRealVar*>(dataDepSet->find(realReal->GetName())) ;
255 if (!datReal) continue ;
256
257 // Check that range of observables in pdf is equal or contained in range of observables in data
258
259 if (!realReal->getBinning().lowBoundFunc() && realReal->getMin()<(datReal->getMin()-1e-6)) {
260 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR minimum of FUNC observable " << arg->GetName()
261 << "(" << realReal->getMin() << ") is smaller than that of "
262 << arg->GetName() << " in the dataset (" << datReal->getMin() << ")" << endl ;
264 return ;
265 }
266
267 if (!realReal->getBinning().highBoundFunc() && realReal->getMax()>(datReal->getMax()+1e-6)) {
268 coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR maximum of FUNC observable " << arg->GetName()
269 << " is larger than that of " << arg->GetName() << " in the dataset" << endl ;
271 return ;
272 }
273 }
274
275 // Copy data and strip entries lost by adjusted fit range, _dataClone ranges will be copied from realDepSet ranges
276 if (rangeName && strlen(rangeName)) {
278 // cout << "RooAbsOptTestStatistic: reducing dataset to fit in range named " << rangeName << " resulting dataset has " << _dataClone->sumEntries() << " events" << endl ;
279 } else {
280 _dataClone = (RooAbsData*) indata.Clone() ;
281 }
282 _ownData = true ;
283
284
285 // ******************************************************************
286 // *** PART 3 *** Make adjustments for fit ranges, if specified *
287 // ******************************************************************
288
289 std::unique_ptr<RooArgSet> origObsSet( real.getObservables(indata) );
290 if (rangeName && strlen(rangeName)) {
291 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") constructing test statistic for sub-range named " << rangeName << endl ;
292
293 if(auto pdfClone = dynamic_cast<RooAbsPdf*>(_funcClone)) {
294 pdfClone->setNormRange(rangeName);
295 }
296
297 // Print warnings if the requested ranges are not available for the observable
298 for (const auto arg : *_funcObsSet) {
299
300 if (auto realObs = dynamic_cast<RooRealVar*>(arg)) {
301
302 auto tokens = ROOT::Split(rangeName, ",");
303 for(std::string const& token : tokens) {
304 if(!realObs->hasRange(token.c_str())) {
305 std::stringstream errMsg;
306 errMsg << "The observable \"" << realObs->GetName() << "\" doesn't define the requested range \""
307 << token << "\". Replacing it with the default range." << std::endl;
308 coutI(Fitting) << errMsg.str() << std::endl;
309 }
310 }
311 }
312 }
313 }
314
315
316 // ******************************************************************
317 // *** PART 3.2 *** Binned fits *
318 // ******************************************************************
319
321
322
323 // Fix RooAddPdf coefficients to original normalization range
324 if (rangeName && strlen(rangeName)) {
325
326 // WVE Remove projected dependents from normalization
328
329 if (addCoefRangeName && strlen(addCoefRangeName)) {
330 cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
331 << ") fixing interpretation of coefficients of any RooAddPdf component to range " << addCoefRangeName << endl ;
332 _funcClone->fixAddCoefRange(addCoefRangeName,false) ;
333 }
334 }
335
336
337 // This is deferred from part 2 - but must happen after part 3 - otherwise invalid bins cannot be properly marked in cacheValidEntries
340
341
342
343
344 // *********************************************************************
345 // *** PART 4 *** Adjust normalization range for projected observables *
346 // *********************************************************************
347
348 // Remove projected dependents from normalization set
349 if (projDeps.getSize()>0) {
350
351 _projDeps = new RooArgSet;
352 projDeps.snapshot(*_projDeps, false) ;
353
354 //RooArgSet* tobedel = (RooArgSet*) _normSet->selectCommon(*_projDeps) ;
355 _normSet->remove(*_projDeps,true,true) ;
356
357 // Mark all projected dependents as such
359 projDataDeps->setAttribAll("projectedDependent") ;
360 delete projDataDeps ;
361 }
362
363
364 coutI(Optimization) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") optimizing internal clone of p.d.f for likelihood evaluation."
365 << "Lazy evaluation and associated change tracking will disabled for all nodes that depend on observables" << endl ;
366
367
368 // *********************************************************************
369 // *** PART 4 *** Finalization and activation of optimization *
370 // *********************************************************************
371
372 // Redirect pointers of base class to clone
373 _func = _funcClone ;
374 _data = _dataClone ;
375
377
379
380 // It would be unusual if the global observables are used in the likelihood
381 // outside of the constraint terms, but if they are we have to be consistent
382 // and also redirect them to the snapshots in the dataset if appropriate.
385 }
386
387}
388
389
390////////////////////////////////////////////////////////////////////////////////
391/// Destructor
392
394{
395 if (operMode()==Slave) {
396 delete _funcClone ;
397 delete _funcObsSet ;
398 if (_projDeps) {
399 delete _projDeps ;
400 }
401 if (_ownData) {
402 delete _dataClone ;
403 }
404 }
405 delete _normSet ;
406}
407
408
409
410////////////////////////////////////////////////////////////////////////////////
411/// Method to combined test statistic results calculated into partitions into
412/// the global result. This default implementation adds the partition return
413/// values
414
416{
417 // Default implementation returns sum of components
418 double sum(0), carry(0);
419 for (Int_t i = 0; i < n; ++i) {
420 double y = array[i]->getValV();
421 carry += reinterpret_cast<RooAbsOptTestStatistic*>(array[i])->getCarry();
422 y -= carry;
423 const double t = sum + y;
424 carry = (t - sum) - y;
425 sum = t;
426 }
427 _evalCarry = carry;
428 return sum ;
429}
430
431
432
433////////////////////////////////////////////////////////////////////////////////
434/// Catch server redirect calls and forward to internal clone of function
435
436bool RooAbsOptTestStatistic::redirectServersHook(const RooAbsCollection& newServerList, bool mustReplaceAll, bool nameChange, bool isRecursive)
437{
438 RooAbsTestStatistic::redirectServersHook(newServerList,mustReplaceAll,nameChange,isRecursive) ;
439 if (operMode()!=Slave) return false ;
440 bool ret = _funcClone->recursiveRedirectServers(newServerList,false,nameChange) ;
441 return ret || RooAbsReal::redirectServersHook(newServerList, mustReplaceAll, nameChange, isRecursive);
442}
443
444
445
446////////////////////////////////////////////////////////////////////////////////
447/// Catch print hook function and forward to function clone
448
450{
452 if (operMode()!=Slave) return ;
453 TString indent2(indent) ;
454 indent2 += "opt >>" ;
455 _funcClone->printCompactTree(os,indent2.Data()) ;
456 os << indent2 << " dataset clone = " << _dataClone << " first obs = " << _dataClone->get()->first() << endl ;
457}
458
459
460
461////////////////////////////////////////////////////////////////////////////////
462/// Driver function to propagate constant term optimizations in test statistic.
463/// If code Activate is sent, constant term optimization will be executed.
464/// If code Deactivate is sent, any existing constant term optimizations will
465/// be abandoned. If codes ConfigChange or ValueChange are sent, any existing
466/// constant term optimizations will be redone.
467
469{
470 // cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump BEFORE const-opt" << endl ;
471 // _funcClone->Print("t") ;
472
473 RooAbsTestStatistic::constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
474 if (operMode()!=Slave) return ;
475
476 if (_dataClone->hasFilledCache() && _dataClone->store()->cacheOwner()!=this) {
477 if (opcode==Activate) {
478 cxcoutW(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
479 << ") dataset cache is owned by another object, no constant term optimization can be applied" << endl ;
480 }
481 return ;
482 }
483
484 if (!allowFunctionCache()) {
485 if (opcode==Activate) {
486 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
487 << ") function caching prohibited by test statistic, no constant term optimization is applied" << endl ;
488 }
489 return ;
490 }
491
492 if (_dataClone->hasFilledCache() && opcode==Activate) {
493 opcode=ValueChange ;
494 }
495
496 switch(opcode) {
497 case Activate:
498 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
499 << ") optimizing evaluation of test statistic by finding all nodes in p.d.f that depend exclusively"
500 << " on observables and constant parameters and precalculating their values" << endl ;
501 optimizeConstantTerms(true,doAlsoTrackingOpt) ;
502 break ;
503
504 case DeActivate:
505 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
506 << ") deactivating optimization of constant terms in test statistic" << endl ;
507 optimizeConstantTerms(false) ;
508 break ;
509
510 case ConfigChange:
511 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
512 << ") one ore more parameter were changed from constant to floating or vice versa, "
513 << "re-evaluating constant term optimization" << endl ;
514 optimizeConstantTerms(false) ;
515 optimizeConstantTerms(true,doAlsoTrackingOpt) ;
516 break ;
517
518 case ValueChange:
519 cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
520 << ") the value of one ore more constant parameter were changed re-evaluating constant term optimization" << endl ;
521 // Request a forcible cache update of all cached nodes
523
524 break ;
525 }
526
527// cout << "ROATS::constOpt(" << GetName() << ") funcClone structure dump AFTER const-opt" << endl ;
528// _funcClone->Print("t") ;
529}
530
531
532
533////////////////////////////////////////////////////////////////////////////////
534/// This method changes the value caching logic for all nodes that depends on any of the observables
535/// as defined by the given dataset. When evaluating a test statistic constructed from the RooAbsReal
536/// with a dataset the observables are guaranteed to change with every call, thus there is no point
537/// in tracking these changes which result in a net overhead. Thus for observable-dependent nodes,
538/// the evaluation mechanism is changed from being dependent on a 'valueDirty' flag to guaranteed evaluation.
539/// On the dataset side, the observables objects are modified to no longer send valueDirty messages
540/// to their client
541
543{
544// cout << "RooAbsOptTestStatistic::optimizeCaching(" << GetName() << "," << this << ")" << endl ;
545
546 // Trigger create of all object caches now in nodes that have deferred object creation
547 // so that cache contents can be processed immediately
549
550 // Set value caching mode for all nodes that depend on any of the observables to ADirty
552
553 // Disable propagation of dirty state flags for observables
554 _dataClone->setDirtyProp(false) ;
555
556 // Disable reading of observables that are not used
558}
559
560
561
562////////////////////////////////////////////////////////////////////////////////
563/// Driver function to activate global constant term optimization.
564/// If activated, constant terms are found and cached with the dataset.
565/// The operation mode of cached nodes is set to AClean meaning that
566/// their getVal() call will never result in an evaluate call.
567/// Finally the branches in the dataset that correspond to observables
568/// that are exclusively used in constant terms are disabled as
569/// they serve no more purpose
570
571void RooAbsOptTestStatistic::optimizeConstantTerms(bool activate, bool applyTrackingOpt)
572{
573 if(activate) {
574
575 if (_optimized) {
576 return ;
577 }
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
584 // WVE - Patch to allow customization of optimization level per component pdf
585 if (_funcClone->getAttribute("NoOptimizeLevel1")) {
586 coutI(Minimization) << " Optimization customization: Level-1 constant-term optimization prohibited by attribute NoOptimizeLevel1 set on top-level pdf "
587 << _funcClone->ClassName() << "::" << _funcClone->GetName() << endl ;
588 return ;
589 }
590 if (_funcClone->getAttribute("NoOptimizeLevel2")) {
591 coutI(Minimization) << " Optimization customization: Level-2 constant-term optimization prohibited by attribute NoOptimizeLevel2 set on top-level pdf "
592 << _funcClone->ClassName() << "::" << _funcClone->GetName() << endl ;
593 applyTrackingOpt=false ;
594 }
595
596 // Apply tracking optimization here. Default strategy is to track components
597 // of RooAddPdfs and RooRealSumPdfs. If these components are a RooProdPdf
598 // or a RooProduct respectively, track the components of these products instead
599 // of the product term
600 RooArgSet trackNodes ;
601
602
603 // Add safety check here - applyTrackingOpt will only be applied if present
604 // dataset is constructed in terms of a RooVectorDataStore
605 if (applyTrackingOpt) {
606 if (!dynamic_cast<RooVectorDataStore*>(_dataClone->store())) {
607 coutW(Optimization) << "RooAbsOptTestStatistic::optimizeConstantTerms(" << GetName()
608 << ") WARNING Cache-and-track optimization (Optimize level 2) is only available for datasets"
609 << " implement in terms of RooVectorDataStore - ignoring this option for current dataset" << endl ;
610 applyTrackingOpt = false ;
611 }
612 }
613
614 if (applyTrackingOpt) {
615 RooArgSet branches ;
616 _funcClone->branchNodeServerList(&branches) ;
617 for (auto arg : branches) {
618 arg->setCacheAndTrackHints(trackNodes);
619 }
620 // Do not set CacheAndTrack on constant expressions
621 RooArgSet* constNodes = (RooArgSet*) trackNodes.selectByAttrib("Constant",true) ;
622 trackNodes.remove(*constNodes) ;
623 delete constNodes ;
624
625 // Set CacheAndTrack flag on all remaining nodes
626 trackNodes.setAttribAll("CacheAndTrack",true) ;
627 }
628
629 // Find all nodes that depend exclusively on constant parameters
631
633
634 // Cache constant nodes with dataset - also cache entries corresponding to zero-weights in data when using BinnedLikelihood
635 _dataClone->cacheArgs(this,_cachedNodes,_normSet,!_funcClone->getAttribute("BinnedLikelihood")) ;
636
637 // Put all cached nodes in AClean value caching mode so that their evaluate() is never called
638 for (auto cacheArg : _cachedNodes) {
639 cacheArg->setOperMode(RooAbsArg::AClean) ;
640 }
641
642 RooArgSet* constNodes = (RooArgSet*) _cachedNodes.selectByAttrib("ConstantExpressionCached",true) ;
643 RooArgSet actualTrackNodes(_cachedNodes) ;
644 actualTrackNodes.remove(*constNodes) ;
645 if (constNodes->getSize()>0) {
646 if (constNodes->getSize()<20) {
647 coutI(Minimization) << " The following expressions have been identified as constant and will be precalculated and cached: " << *constNodes << endl ;
648 } else {
649 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions have been identified as constant and will be precalculated and cached." << endl ;
650 }
651 }
652 if (actualTrackNodes.getSize()>0) {
653 if (actualTrackNodes.getSize()<20) {
654 coutI(Minimization) << " The following expressions will be evaluated in cache-and-track mode: " << actualTrackNodes << endl ;
655 } else {
656 coutI(Minimization) << " A total of " << constNodes->getSize() << " expressions will be evaluated in cache-and-track-mode." << endl ;
657 }
658 }
659 delete constNodes ;
660
661 // Disable reading of observables that are no longer used
663
664 _optimized = true ;
665
666 } else {
667
668 // Delete the cache
670
671 // Reactivate all tree branches
673
674 // Reset all nodes to ADirty
676
677 // Disable propagation of dirty state flags for observables
678 _dataClone->setDirtyProp(false) ;
679
681
682
683 _optimized = false ;
684 }
685}
686
687
688
689////////////////////////////////////////////////////////////////////////////////
690/// Change dataset that is used to given one. If cloneData is true, a clone of
691/// in the input dataset is made. If the test statistic was constructed with
692/// a range specification on the data, the cloneData argument is ignored and
693/// the data is always cloned.
694bool RooAbsOptTestStatistic::setDataSlave(RooAbsData& indata, bool cloneData, bool ownNewData)
695{
696
697 if (operMode()==SimMaster) {
698 //cout << "ROATS::setDataSlave() ERROR this is SimMaster _funcClone = " << _funcClone << endl ;
699 return false ;
700 }
701
702 //cout << "ROATS::setDataSlave() new dataset size = " << indata.numEntries() << endl ;
703 //indata.Print("v") ;
704
705
706 // If the current dataset is owned, transfer the ownership to unique pointer
707 // that will get out of scope at the end of this function. We can't delete it
708 // right now, because there might be global observables in the model that
709 // first need to be redirected to the new dataset with a later call to
710 // RooAbsArg::recursiveRedirectServers.
711 std::unique_ptr<RooAbsData> oldOwnedData;
712 if (_ownData) {
713 oldOwnedData.reset(_dataClone);
714 _dataClone = nullptr ;
715 }
716
717 if (!cloneData && _rangeName.size()>0) {
718 coutW(InputArguments) << "RooAbsOptTestStatistic::setData(" << GetName() << ") WARNING: test statistic was constructed with range selection on data, "
719 << "ignoring request to _not_ clone the input dataset" << endl ;
720 cloneData = true ;
721 }
722
723 if (cloneData) {
724 // Cloning input dataset
725 if (_rangeName.empty()) {
726 _dataClone = (RooAbsData*) indata.reduce(*indata.get()) ;
727 } else {
729 }
730 _ownData = true ;
731
732 } else {
733
734 // Taking input dataset
735 _dataClone = &indata ;
736 _ownData = ownNewData ;
737
738 }
739
740 // Attach function clone to dataset
742 _dataClone->setDirtyProp(false) ;
743 _data = _dataClone ;
744
745 // ReCache constant nodes with dataset
746 if (_cachedNodes.getSize()>0) {
748 }
749
750 // Adjust internal event count
751 setEventCount(indata.numEntries()) ;
752
753 setValueDirty() ;
754
755 // It would be unusual if the global observables are used in the likelihood
756 // outside of the constraint terms, but if they are we have to be consistent
757 // and also redirect them to the snapshots in the dataset if appropriate.
760 }
761
762 return true ;
763}
764
765
766
767
768////////////////////////////////////////////////////////////////////////////////
769
771{
772 if (_sealed) {
773 bool notice = (sealNotice() && strlen(sealNotice())) ;
774 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
775 << ") WARNING: object sealed by creator - access to data is not permitted: "
776 << (notice?sealNotice():"<no user notice>") << endl ;
777 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
778 return dummy ;
779 }
780 return *_dataClone ;
781}
782
783
784////////////////////////////////////////////////////////////////////////////////
785
787{
788 if (_sealed) {
789 bool notice = (sealNotice() && strlen(sealNotice())) ;
790 coutW(ObjectHandling) << "RooAbsOptTestStatistic::data(" << GetName()
791 << ") WARNING: object sealed by creator - access to data is not permitted: "
792 << (notice?sealNotice():"<no user notice>") << endl ;
793 static RooDataSet dummy ("dummy","dummy",RooArgSet()) ;
794 return dummy ;
795 }
796 return *_dataClone ;
797}
798
799
800////////////////////////////////////////////////////////////////////////////////
801/// Inspect PDF to find out if we are doing a binned fit to a 1-dimensional unbinned PDF.
802/// If this is the case, enable finer sampling of bins by wrapping PDF into a RooBinSamplingPdf.
803/// The member _integrateBinsPrecision decides how we act:
804/// - < 0: Don't do anything.
805/// - = 0: Only enable feature if fitting unbinned PDF to RooDataHist.
806/// - > 0: Enable as requested.
808
809 auto& pdf = static_cast<RooAbsPdf&>(*_funcClone);
812 _funcClone = newPdf.release();
813 }
814
815}
816
817
818/// Returns a suffix string that is unique for RooAbsOptTestStatistic
819/// instances that don't share the same cloned input data object.
821 return Form("_%lx", _dataClone->uniqueId().value()) ;
822}
823
#define e(i)
Definition RSha256.hxx:103
#define coutI(a)
#define cxcoutI(a)
#define coutW(a)
#define cxcoutW(a)
#define coutE(a)
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2468
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
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...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
bool 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 ...
void printCompactTree(const char *indent="", const char *fileName=nullptr, const char *namePat=nullptr, RooAbsArg *client=nullptr)
Print tree structure of expression tree on stdout, or to file if filename is specified.
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition RooAbsArg.h:492
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
virtual void optimizeCacheMode(const RooArgSet &observables)
Activate cache mode optimization with given definition of observables.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
virtual RooAbsReal * highBoundFunc() const
Return pointer to RooAbsReal parameterized upper bound, if any.
virtual RooAbsReal * lowBoundFunc() const
Return pointer to RooAbsReal parameterized lower bound, if any.
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
RooAbsCollection * selectByAttrib(const char *name, bool value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
Int_t getSize() const
Return the number of elements in the collection.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void setAttribAll(const Text_t *name, bool value=true)
Set given attribute in each element of the collection by calling each elements setAttribute() functio...
Storage_t::size_type size() const
RooAbsArg * first() const
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...
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:58
virtual const RooArgSet * get() const
Definition RooAbsData.h:102
RooAbsDataStore * store()
Definition RooAbsData.h:78
RooFit::UniqueId< RooAbsData > const & uniqueId() const
Returns a unique ID that is different for every instantiated RooAbsData object.
Definition RooAbsData.h:314
void setDirtyProp(bool flag)
Control propagation of dirty flags from observables in dataset.
virtual void setArgStatus(const RooArgSet &set, bool active)
virtual void cacheArgs(const RooAbsArg *owner, RooArgSet &varSet, const RooArgSet *nset=nullptr, bool skipZeroWeights=false)
Internal method – Cache given set of functions with data.
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'.
bool hasFilledCache() const
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
RooArgSet const * getGlobalObservables() const
Returns snapshot of global observables stored in this data.
Definition RooAbsData.h:294
virtual void resetCache()
Internal method – Remove cached function values.
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.
void attachBuffers(const RooArgSet &extObs)
RooAbsOptTestStatistic is the abstract base class for test statistics objects that evaluate a functio...
bool setDataSlave(RooAbsData &data, bool cloneData=true, bool ownNewDataAnyway=false) override
Change dataset that is used to given one.
~RooAbsOptTestStatistic() override
Destructor.
RooAbsReal * _funcClone
Pointer to internal clone of input function.
bool _sealed
Is test statistic sealed – i.e. no access to data.
void optimizeConstantTerms(bool, bool=true)
Driver function to activate global constant term optimization.
double combinedValue(RooAbsReal **gofArray, Int_t nVal) const override
Method to combined test statistic results calculated into partitions into the global result.
RooAbsReal * _origFunc
Original function.
bool _ownData
Do we own the dataset.
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
RooAbsData * _origData
Original data.
RooArgSet * _funcObsSet
List of observables in the pdf expression.
void constOptimizeTestStatistic(ConstOpCode opcode, bool doAlsoTrackingOpt=true) override
Driver function to propagate constant term optimizations in test statistic.
void setUpBinSampling()
Inspect PDF to find out if we are doing a binned fit to a 1-dimensional unbinned PDF.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursive) override
Catch server redirect calls and forward to internal clone of function.
RooArgSet _cachedNodes
! List of nodes that are cached as constant expressions
void initSlave(RooAbsReal &real, RooAbsData &indata, const RooArgSet &projDeps, const char *rangeName, const char *addCoefRangeName)
void printCompactTreeHook(std::ostream &os, const char *indent="") override
Catch print hook function and forward to function clone.
RooArgSet * _normSet
Pointer to set with observables used for normalization.
const char * cacheUniqueSuffix() const override
Returns a suffix string that is unique for RooAbsOptTestStatistic instances that don't share the same...
RooArgSet * _funcCloneSet
Set owning all components of internal clone of input function.
RooAbsData * _dataClone
Pointer to internal clone if input data.
virtual RooArgSet requiredExtraObservables() const
RooAbsOptTestStatistic()
Default Constructor.
RooArgSet * _projDeps
Set of projected observable.
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
virtual double getMin(const char *name=nullptr) const
Get minimum 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
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:105
virtual double getValV(const RooArgSet *normalisationSet=nullptr) const
Return value of object.
virtual void fixAddCoefNormalization(const RooArgSet &addNormSet=RooArgSet(), bool force=true)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
A buffer for reading values from trees.
virtual void fixAddCoefRange(const char *rangeName=nullptr, bool force=true)
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.
double _evalCarry
! carry of Kahan sum in evaluatePartition
std::string _addCoefRangeName
Name of reference to be used for RooAddPdf components.
GOFOpMode operMode() const
RooSetProxy _paramSet
Parameters of the test statistic (=parameters of the input function)
RooAbsReal * _func
Pointer to original input function.
void printCompactTreeHook(std::ostream &os, const char *indent="") override
Add extra information on component test statistics when printing itself as part of a tree structure.
std::string _rangeName
Name of range in which to calculate test statistic.
void constOptimizeTestStatistic(ConstOpCode opcode, bool doAlsoTrackingOpt=true) override
Forward constant term optimization management calls to component test statistics.
void setEventCount(Int_t nEvents)
virtual double getCarry() const
RooAbsData * _data
Pointer to original input dataset.
const bool _takeGlobalObservablesFromData
If the global observable values are taken from data.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursive) override
Forward server redirect calls to component test statistics.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:178
static std::unique_ptr< RooAbsPdf > create(RooAbsPdf &pdf, RooAbsData const &data, double precision)
Creates a wrapping RooBinSamplingPdf if appropriate.
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
RooDataSet is a container class to hold unbinned data.
Definition RooDataSet.h:57
static void softAbort()
Soft abort function that interrupts macro execution but doesn't kill ROOT.
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:40
const RooAbsBinning & getBinning(const char *name=nullptr, bool verbose=true, bool createOnTheFly=false) const override
Return binning definition with name.
RooVectorDataStore uses std::vectors to store data columns.
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:380
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
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
std::unique_ptr< T > cloneTreeWithSameParameters(T const &arg, RooArgSet const *observables=nullptr)
Clone RooAbsArg object and reattach to original parameters.
Definition RooHelpers.h:149
constexpr Value_t value() const
Return numerical value of ID.
Definition UniqueId.h:59
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345