Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooVectorDataStore.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 RooVectorDataStore.cxx
19\class RooVectorDataStore
20\ingroup Roofitcore
21
22RooVectorDataStore uses std::vectors to store data columns. Each of these vectors
23is associated to an instance of a RooAbsReal, whose values it represents. Those
24RooAbsReal are the observables of the dataset.
25In addition to the observables, a data column can be bound to a different instance
26of a RooAbsReal (e.g., the column "x" can be bound to the observable "x" of a computation
27graph using attachBuffers()). In this case, a get() operation writes the value of
28the requested column into the bound real.
29
30As a faster alternative to loading values one-by-one, one can use the function getBatches(),
31which returns spans pointing directly to the data.
32**/
33
34#include "RooVectorDataStore.h"
35
36#include "RooFit.h"
37#include "RooMsgService.h"
38#include "RooTreeDataStore.h"
39#include "RooFormulaVar.h"
40#include "RooRealVar.h"
41#include "RooCategory.h"
42#include "RooHistError.h"
43#include "RooTrace.h"
44#include "RooHelpers.h"
45
46#include "Math/Util.h"
47#include "ROOT/StringUtils.hxx"
48#include "TList.h"
49#include "TBuffer.h"
50
51#include <iomanip>
52using namespace std;
53
56
57
58////////////////////////////////////////////////////////////////////////////////
59
61 _wgtVar(0),
62 _sumWeight(0),
63 _sumWeightCarry(0),
64 _extWgtArray(0),
65 _extWgtErrLoArray(0),
66 _extWgtErrHiArray(0),
67 _extSumW2Array(0),
68 _cache(0),
69 _cacheOwner(0),
70 _forcedUpdate(kFALSE)
71{
73}
74
75
76
77////////////////////////////////////////////////////////////////////////////////
78
79RooVectorDataStore::RooVectorDataStore(std::string_view name, std::string_view title, const RooArgSet& vars, const char* wgtVarName) :
80 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
81 _varsww(vars),
82 _wgtVar(weightVar(vars,wgtVarName)),
83 _sumWeight(0),
84 _sumWeightCarry(0),
85 _extWgtArray(0),
86 _extWgtErrLoArray(0),
87 _extWgtErrHiArray(0),
88 _extSumW2Array(0),
89 _cache(0),
90 _cacheOwner(0),
91 _forcedUpdate(kFALSE)
92{
93 for (auto arg : _varsww) {
94 arg->attachToVStore(*this) ;
95 }
96
99}
100
101
102
103////////////////////////////////////////////////////////////////////////////////
104
106{
107 for (auto realVec : _realStoreList) {
108 realVec->setNativeBuffer();
109 }
110
111 for (auto fullVec : _realfStoreList) {
112 fullVec->setNativeBuffer();
113 }
114
115 for (auto catVec : _catStoreList) {
116 catVec->setNativeBuffer();
117 }
118}
119
120
121
122
123////////////////////////////////////////////////////////////////////////////////
124/// Utility function for constructors
125/// Return RooArgSet that is copy of allVars minus variable matching wgtName if specified
126
127RooArgSet RooVectorDataStore::varsNoWeight(const RooArgSet& allVars, const char* wgtName)
128{
129 RooArgSet ret(allVars) ;
130 if(wgtName) {
131 RooAbsArg* wgt = allVars.find(wgtName) ;
132 if (wgt) {
133 ret.remove(*wgt,kTRUE,kTRUE) ;
134 }
135 }
136 return ret ;
137}
138
139
140
141////////////////////////////////////////////////////////////////////////////////
142/// Utility function for constructors
143/// Return pointer to weight variable if it is defined
144
145RooRealVar* RooVectorDataStore::weightVar(const RooArgSet& allVars, const char* wgtName)
146{
147 if(wgtName) {
148 RooRealVar* wgt = dynamic_cast<RooRealVar*>(allVars.find(wgtName)) ;
149 return wgt ;
150 }
151 return 0 ;
152}
153
154
155
156
157////////////////////////////////////////////////////////////////////////////////
158/// Regular copy ctor
159
161 RooAbsDataStore(other,newname),
162 _varsww(other._varsww),
163 _wgtVar(other._wgtVar),
164 _sumWeight(other._sumWeight),
165 _sumWeightCarry(other._sumWeightCarry),
166 _extWgtArray(other._extWgtArray),
167 _extWgtErrLoArray(other._extWgtErrLoArray),
168 _extWgtErrHiArray(other._extWgtErrHiArray),
169 _extSumW2Array(other._extSumW2Array),
170 _currentWeightIndex(other._currentWeightIndex),
171 _cache(0),
172 _cacheOwner(0),
173 _forcedUpdate(kFALSE)
174{
175 for (const auto realVec : other._realStoreList) {
176 _realStoreList.push_back(new RealVector(*realVec, (RooAbsReal*)_varsww.find(realVec->_nativeReal->GetName()))) ;
177 }
178
179 for (const auto realFullVec : other._realfStoreList) {
180 _realfStoreList.push_back(new RealFullVector(*realFullVec, (RooAbsReal*)_varsww.find(realFullVec->_nativeReal->GetName()))) ;
181 }
182
183 for (const auto catVec : other._catStoreList) {
184 _catStoreList.push_back(new CatVector(*catVec, (RooAbsCategory*)_varsww.find(catVec->_cat->GetName()))) ;
185 }
186
188
190}
191
192
193////////////////////////////////////////////////////////////////////////////////
194
195RooVectorDataStore::RooVectorDataStore(const RooTreeDataStore& other, const RooArgSet& vars, const char* newname) :
196 RooAbsDataStore(other,varsNoWeight(vars,other._wgtVar?other._wgtVar->GetName():0),newname),
197 _varsww(vars),
198 _wgtVar(weightVar(vars,other._wgtVar?other._wgtVar->GetName():0)),
199 _sumWeight(0),
200 _sumWeightCarry(0),
201 _extWgtArray(0),
202 _extWgtErrLoArray(0),
203 _extWgtErrHiArray(0),
204 _extSumW2Array(0),
205 _currentWeightIndex(0),
206 _cache(0),
207 _cacheOwner(0),
208 _forcedUpdate(kFALSE)
209{
210 for (const auto arg : _varsww) {
211 arg->attachToVStore(*this) ;
212 }
213
215
216 // now copy contents of tree storage here
217 reserve(other.numEntries());
218 for (Int_t i=0 ; i<other.numEntries() ; i++) {
219 other.get(i) ;
220 _varsww.assign(other._varsww) ;
221 fill() ;
222 }
224
225}
226
227
228////////////////////////////////////////////////////////////////////////////////
229/// Clone ctor, must connect internal storage to given new external set of vars
230
231RooVectorDataStore::RooVectorDataStore(const RooVectorDataStore& other, const RooArgSet& vars, const char* newname) :
232 RooAbsDataStore(other,varsNoWeight(vars,other._wgtVar?other._wgtVar->GetName():0),newname),
233 _varsww(vars),
234 _wgtVar(other._wgtVar?weightVar(vars,other._wgtVar->GetName()):0),
235 _sumWeight(other._sumWeight),
236 _sumWeightCarry(other._sumWeightCarry),
237 _extWgtArray(other._extWgtArray),
238 _extWgtErrLoArray(other._extWgtErrLoArray),
239 _extWgtErrHiArray(other._extWgtErrHiArray),
240 _extSumW2Array(other._extSumW2Array),
241 _currentWeightIndex(other._currentWeightIndex),
242 _cache(0),
243 _forcedUpdate(kFALSE)
244{
245 for (const auto realVec : other._realStoreList) {
246 auto real = static_cast<RooAbsReal*>(vars.find(realVec->bufArg()->GetName()));
247 if (real) {
248 // Clone vector
249 _realStoreList.push_back(new RealVector(*realVec, real)) ;
250 // Adjust buffer pointer
251 real->attachToVStore(*this) ;
252 }
253 }
254
255 vector<RealFullVector*>::const_iterator fiter = other._realfStoreList.begin() ;
256 for (; fiter!=other._realfStoreList.end() ; ++fiter) {
257 RooAbsReal* real = (RooAbsReal*) vars.find((*fiter)->bufArg()->GetName()) ;
258 if (real) {
259 // Clone vector
260 _realfStoreList.push_back(new RealFullVector(**fiter,real)) ;
261 // Adjust buffer pointer
262 real->attachToVStore(*this) ;
263 }
264 }
265
266 vector<CatVector*>::const_iterator citer = other._catStoreList.begin() ;
267 for (; citer!=other._catStoreList.end() ; ++citer) {
268 RooAbsCategory* cat = (RooAbsCategory*) vars.find((*citer)->bufArg()->GetName()) ;
269 if (cat) {
270 // Clone vector
271 _catStoreList.push_back(new CatVector(**citer,cat)) ;
272 // Adjust buffer pointer
273 cat->attachToVStore(*this) ;
274 }
275 }
276
278
280
281}
282
283
284
285
286
287////////////////////////////////////////////////////////////////////////////////
288
289RooVectorDataStore::RooVectorDataStore(std::string_view name, std::string_view title, RooAbsDataStore& tds,
290 const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
291 std::size_t nStart, std::size_t nStop, Bool_t /*copyCache*/, const char* wgtVarName) :
292
293 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
294 _varsww(vars),
295 _wgtVar(weightVar(vars,wgtVarName)),
296 _sumWeight(0),
297 _sumWeightCarry(0),
298 _extWgtArray(0),
299 _extWgtErrLoArray(0),
300 _extWgtErrHiArray(0),
301 _extSumW2Array(0),
302 _cache(0),
303 _forcedUpdate(kFALSE)
304{
305 for (const auto arg : _varsww) {
306 arg->attachToVStore(*this) ;
307 }
308
310
311 // Deep clone cutVar and attach clone to this dataset
312 RooFormulaVar* cloneVar = 0;
313 if (cutVar) {
314 cloneVar = (RooFormulaVar*) cutVar->cloneTree() ;
315 cloneVar->attachDataStore(tds) ;
316 }
317
318 RooVectorDataStore* vds = dynamic_cast<RooVectorDataStore*>(&tds) ;
319 if (vds && vds->_cache) {
320 _cache = new RooVectorDataStore(*vds->_cache) ;
321 }
322
323 loadValues(&tds,cloneVar,cutRange,nStart,nStop);
324
325 delete cloneVar ;
327}
328
329
330
331
332
333
334////////////////////////////////////////////////////////////////////////////////
335/// Destructor
336
338{
339 for (auto elm : _realStoreList) {
340 delete elm;
341 }
342
343 for (auto elm : _realfStoreList) {
344 delete elm;
345 }
346
347 for (auto elm : _catStoreList) {
348 delete elm;
349 }
350
351 delete _cache ;
353}
354
355
356////////////////////////////////////////////////////////////////////////////////
357/// Interface function to TTree::Fill
358
360{
361 for (auto realVec : _realStoreList) {
362 realVec->fill() ;
363 }
364
365 for (auto fullVec : _realfStoreList) {
366 fullVec->fill() ;
367 }
368
369 for (auto catVec : _catStoreList) {
370 catVec->fill() ;
371 }
372 // use Kahan's algorithm to sum up weights to avoid loss of precision
374 Double_t t = _sumWeight + y;
375 _sumWeightCarry = (t - _sumWeight) - y;
376 _sumWeight = t;
377
378 return 0 ;
379}
380
381
382
383////////////////////////////////////////////////////////////////////////////////
384/// Load the n-th data point (n='index') into the variables of this dataset,
385/// and return a pointer to the RooArgSet that holds them.
387{
388 if (index < 0 || static_cast<std::size_t>(index) >= size()) return 0;
389
390 for (const auto realV : _realStoreList) {
391 realV->load(index);
392 }
393
394 for (const auto fullRealP : _realfStoreList) {
395 fullRealP->get(index);
396 }
397
398 for (const auto catP : _catStoreList) {
399 catP->load(index);
400 }
401
402 if (_doDirtyProp) {
403 // Raise all dirty flags
404 for (auto var : _vars) {
405 var->setValueDirty(); // This triggers recalculation of all clients
406 }
407 }
408
409 // Update current weight cache
410 _currentWeightIndex = index;
411
412 if (_cache) {
413 _cache->get(index) ;
414 }
415
416 return &_vars;
417}
418
419
420////////////////////////////////////////////////////////////////////////////////
421/// Load the n-th data point (n='index') into the variables of this dataset,
422/// and return a pointer to the RooArgSet that holds them.
424{
425 if (index < 0 || static_cast<std::size_t>(index) >= size()) return 0;
426
427 for (const auto realV : _realStoreList) {
428 realV->loadToNative(index) ;
429 }
430
431 for (const auto fullRealP : _realfStoreList) {
432 fullRealP->loadToNative(index);
433 }
434
435 for (const auto catP : _catStoreList) {
436 catP->loadToNative(index);
437 }
438
439 if (_doDirtyProp) {
440 // Raise all dirty flags
441 for (auto var : _vars) {
442 var->setValueDirty() ; // This triggers recalculation of all clients
443 }
444 }
445
446 // Update current weight cache
447 _currentWeightIndex = index;
448
449 if (_cache) {
450 _cache->getNative(index) ;
451 }
452
453 return &_vars;
454}
455
456
457////////////////////////////////////////////////////////////////////////////////
458/// Return the error of the current weight.
459/// @param[in] etype Switch between simple Poisson or sum-of-weights statistics
460
462{
463 if (_extWgtArray) {
464
465 // We have a weight array, use that info
466
467 // Return symmetric error on current bin calculated either from Poisson statistics or from SumOfWeights
468 Double_t lo = 0, hi = 0 ;
469 weightError(lo,hi,etype) ;
470 return (lo+hi)/2 ;
471
472 } else if (_wgtVar) {
473
474 // We have a a weight variable, use that info
475 if (_wgtVar->hasAsymError()) {
476 return ( _wgtVar->getAsymErrorHi() - _wgtVar->getAsymErrorLo() ) / 2 ;
477 } else if (_wgtVar->hasError(kFALSE)) {
478 return _wgtVar->getError();
479 } else {
480 return 0 ;
481 }
482
483 } else {
484
485 // We have no weights
486 return 0 ;
487
488 }
489}
490
491
492
493////////////////////////////////////////////////////////////////////////////////
494
496{
497 if (_extWgtArray) {
498 double wgt;
499
500 // We have a weight array, use that info
501 switch (etype) {
502
503 case RooAbsData::Auto:
504 throw string(Form("RooDataHist::weightError(%s) error type Auto not allowed here",GetName())) ;
505 break ;
506
508 throw string(Form("RooDataHist::weightError(%s) error type Expected not allowed here",GetName())) ;
509 break ;
510
512 // Weight may be preset or precalculated
516 return ;
517 }
518
519 // Otherwise Calculate poisson errors
520 wgt = weight();
521 Double_t ym,yp ;
523 lo = wgt-ym;
524 hi = yp-wgt;
525 return ;
526
529 hi = lo;
530 return ;
531
532 case RooAbsData::None:
533 lo = 0 ;
534 hi = 0 ;
535 return ;
536 }
537
538 } else if (_wgtVar) {
539
540 // We have a a weight variable, use that info
541 if (_wgtVar->hasAsymError()) {
543 lo = _wgtVar->getAsymErrorLo() ;
544 } else {
545 hi = _wgtVar->getError() ;
546 lo = _wgtVar->getError() ;
547 }
548
549 } else {
550
551 // We are unweighted
552 lo=0 ;
553 hi=0 ;
554
555 }
556}
557
558
559
560////////////////////////////////////////////////////////////////////////////////
561///
562
563void RooVectorDataStore::loadValues(const RooAbsDataStore *ads, const RooFormulaVar* select, const char* rangeName, std::size_t nStart, std::size_t nStop)
564{
565 // Load values from dataset 't' into this data collection, optionally
566 // selecting events using 'select' RooFormulaVar
567 //
568
569 // Redirect formula servers to source data row
570 std::unique_ptr<RooFormulaVar> selectClone;
571 if (select) {
572 selectClone.reset( static_cast<RooFormulaVar*>(select->cloneTree()) );
573 selectClone->recursiveRedirectServers(*ads->get()) ;
574 selectClone->setOperMode(RooAbsArg::ADirty,kTRUE) ;
575 }
576
577 // Force DS internal initialization
578 ads->get(0) ;
579
580 // Loop over events in source tree
581 const auto numEntr = static_cast<std::size_t>(ads->numEntries());
582 const std::size_t nevent = nStop < numEntr ? nStop : numEntr;
583
584 auto TDS = dynamic_cast<const RooTreeDataStore*>(ads);
585 auto VDS = dynamic_cast<const RooVectorDataStore*>(ads);
586
587 // Check if weight is being renamed - if so set flag to enable special handling in copy loop
588 Bool_t weightRename(kFALSE) ;
589 Bool_t newWeightVar = _wgtVar ? _wgtVar->getAttribute("NewWeight") : kFALSE ;
590
591 if (_wgtVar && VDS && ((RooVectorDataStore*)(ads))->_wgtVar) {
592 if (string(_wgtVar->GetName())!=((RooVectorDataStore*)(ads))->_wgtVar->GetName() && !newWeightVar) {
593 weightRename=kTRUE ;
594 }
595 }
596 if (_wgtVar && TDS && ((RooTreeDataStore*)(ads))->_wgtVar) {
597 if (string(_wgtVar->GetName())!=((RooTreeDataStore*)(ads))->_wgtVar->GetName() && !newWeightVar) {
598 weightRename=kTRUE ;
599 }
600 }
601
602 std::vector<std::string> ranges;
603 if (rangeName) {
604 ranges = ROOT::Split(rangeName, ",");
605 }
606
607 reserve(numEntries() + (nevent - nStart));
608 for(auto i=nStart; i < nevent ; ++i) {
609 ads->get(i);
610
611 // Does this event pass the cuts?
612 if (selectClone && selectClone->getVal()==0) {
613 continue ;
614 }
615
616 if (TDS) {
617 _varsww.assignValueOnly(TDS->_varsww) ;
618 if (weightRename) {
619 _wgtVar->setVal(TDS->_wgtVar->getVal()) ;
620 }
621 } else if (VDS) {
622 _varsww.assignValueOnly(VDS->_varsww) ;
623 if (weightRename) {
624 _wgtVar->setVal(VDS->_wgtVar->getVal()) ;
625 }
626 } else {
627 _varsww.assignValueOnly(*ads->get()) ;
628 }
629
630 // Check that all copied values are valid and in range
631 bool allValid = true;
632 for (const auto arg : _varsww) {
633 allValid &= arg->isValid();
634 if (allValid && !ranges.empty()) {
635 // If we have one or multiple ranges to be selected, the value
636 // must be in one of them to be valid
637 allValid &= std::any_of(ranges.begin(), ranges.end(), [arg](const std::string& range){
638 return arg->inRange(range.c_str());});
639 }
640 if (!allValid)
641 break ;
642 }
643
644 if (!allValid) {
645 continue ;
646 }
647
648 fill() ;
649 }
650
651 SetTitle(ads->GetTitle());
652}
653
654
655
656
657
658////////////////////////////////////////////////////////////////////////////////
659
660Bool_t RooVectorDataStore::changeObservableName(const char* /*from*/, const char* /*to*/)
661{
662 return kFALSE ;
663}
664
665
666
667////////////////////////////////////////////////////////////////////////////////
668/// Add a new column to the data set which holds the pre-calculated values
669/// of 'newVar'. This operation is only meaningful if 'newVar' is a derived
670/// value.
671///
672/// The return value points to the added element holding 'newVar's value
673/// in the data collection. The element is always the corresponding fundamental
674/// type of 'newVar' (e.g. a RooRealVar if 'newVar' is a RooFormulaVar)
675///
676/// Note: This function is explicitly NOT intended as a speed optimization
677/// opportunity for the user. Components of complex PDFs that can be
678/// precalculated with the dataset are automatically identified as such
679/// and will be precalculated when fitting to a dataset
680///
681/// By forcibly precalculating functions with non-trivial Jacobians,
682/// or functions of multiple variables occurring in the data set,
683/// using addColumn(), you may alter the outcome of the fit.
684///
685/// Only in cases where such a modification of fit behaviour is intentional,
686/// this function should be used.
687
689{
690 // Create a fundamental object of the right type to hold newVar values
691 RooAbsArg* valHolder= newVar.createFundamental();
692 // Sanity check that the holder really is fundamental
693 if(!valHolder->isFundamental()) {
694 coutE(InputArguments) << GetName() << "::addColumn: holder argument is not fundamental: \""
695 << valHolder->GetName() << "\"" << endl;
696 return 0;
697 }
698
699 // Attention: need to do this now, as adding an empty column might give 0 as size
700 const std::size_t numEvt = size();
701
702 // Clone variable and attach to cloned tree
703 RooAbsArg* newVarClone = newVar.cloneTree() ;
705
706 // Attach value place holder to this tree
707 valHolder->attachToVStore(*this) ;
708 _vars.add(*valHolder) ;
709 _varsww.add(*valHolder) ;
710
711 // Fill values of placeholder
712 RealVector* rv(0) ;
713 CatVector* cv(0) ;
714 assert(numEvt != 0);
715 if (dynamic_cast<RooAbsReal*>(valHolder)) {
716 rv = addReal((RooAbsReal*)valHolder);
717 rv->resize(numEvt) ;
718 } else if (dynamic_cast<RooAbsCategory*>((RooAbsCategory*)valHolder)) {
719 cv = addCategory((RooAbsCategory*)valHolder) ;
720 cv->resize(numEvt) ;
721 }
722
723 for (std::size_t i=0; i < numEvt; i++) {
724 getNative(i) ;
725
726 newVarClone->syncCache(&_vars) ;
727 valHolder->copyCache(newVarClone) ;
728
729 if (rv) rv->write(i) ;
730 if (cv) cv->write(i) ;
731 }
732
733 delete newVarClone ;
734 return valHolder ;
735
736}
737
738
739
740////////////////////////////////////////////////////////////////////////////////
741/// Utility function to add multiple columns in one call
742/// See addColumn() for details
743
745{
746 checkInit() ;
747
748 TList cloneSetList ;
749 RooArgSet cloneSet ;
750 RooArgSet* holderSet = new RooArgSet ;
751
752 // Attention: need to do this now, as adding an empty column might give 0 as size
753 const std::size_t numEvt = size();
754
755 for (const auto var : varList) {
756 // Create a fundamental object of the right type to hold newVar values
757 RooAbsArg* valHolder= var->createFundamental();
758 holderSet->add(*valHolder) ;
759
760 // Sanity check that the holder really is fundamental
761 if(!valHolder->isFundamental()) {
762 coutE(InputArguments) << GetName() << "::addColumn: holder argument is not fundamental: \""
763 << valHolder->GetName() << "\"" << endl;
764 return 0;
765 }
766
767 // Clone variable and attach to cloned tree
768 RooArgSet* newVarCloneList = (RooArgSet*) RooArgSet(*var).snapshot() ;
769 if (!newVarCloneList) {
770 coutE(InputArguments) << "RooTreeDataStore::RooTreeData(" << GetName()
771 << ") Couldn't deep-clone variable " << var->GetName() << ", abort." << endl ;
772 return 0 ;
773 }
774 RooAbsArg* newVarClone = newVarCloneList->find(var->GetName()) ;
776 newVarClone->recursiveRedirectServers(*holderSet,kFALSE) ;
777
778 cloneSetList.Add(newVarCloneList) ;
779 cloneSet.add(*newVarClone) ;
780
781 // Attach value place holder to this tree
782 valHolder->attachToVStore(*this) ;
783 _vars.add(*valHolder) ;
784 }
785
786 // Dimension storage area for new vectors
787 for (const auto holder : *holderSet) {
788 if (dynamic_cast<RooAbsReal*>(holder)) {
789 addReal((RooAbsReal*)holder)->resize(numEvt) ;
790 } else {
791 addCategory((RooAbsCategory*)holder)->resize(numEvt);
792 }
793 }
794
795 // Fill values of of placeholder
796 for (std::size_t i=0; i < numEvt; i++) {
797 getNative(i) ;
798
799 for (unsigned int j=0; j < holderSet->size(); ++j) {
800 const auto holder = (*holderSet)[j];
801 const auto cloneArg = cloneSet[j];
802
803 cloneArg->syncCache(&_vars) ;
804
805 holder->copyCache(cloneArg) ;
806
807 if (dynamic_cast<RooAbsReal*>(holder)) {
808 addReal((RooAbsReal*)holder)->write(i) ;
809 } else {
810 addCategory((RooAbsCategory*)holder)->write(i) ;
811 }
812 }
813 }
814
815 cloneSetList.Delete() ;
816 return holderSet ;
817}
818
819
820
821
822////////////////////////////////////////////////////////////////////////////////
823/// Merge columns of supplied data set(s) with this data set. All
824/// data sets must have equal number of entries. In case of
825/// duplicate columns the column of the last dataset in the list
826/// prevails
827
828RooAbsDataStore* RooVectorDataStore::merge(const RooArgSet& allVars, list<RooAbsDataStore*> dstoreList)
829{
830 RooVectorDataStore* mergedStore = new RooVectorDataStore("merged","merged",allVars) ;
831
832 const auto nevt = dstoreList.front()->numEntries();
833 mergedStore->reserve(nevt);
834 for (int i=0 ; i<nevt ; i++) {
835
836 // Copy data from self
837 mergedStore->_vars.assign(*get(i)) ;
838
839 // Copy variables from merge sets
840 for (list<RooAbsDataStore*>::iterator iter = dstoreList.begin() ; iter!=dstoreList.end() ; ++iter) {
841 const RooArgSet* partSet = (*iter)->get(i) ;
842 mergedStore->_vars.assign(*partSet) ;
843 }
844
845 mergedStore->fill() ;
846 }
847 return mergedStore ;
848}
849
850
851
853{
854 for (auto elm : _realStoreList) {
855 elm->reserve(nEvts);
856 }
857
858 for (auto elm : _realfStoreList) {
859 elm->reserve(nEvts);
860 }
861
862 for (auto elm : _catStoreList) {
863 elm->reserve(nEvts);
864 }
865}
866
867////////////////////////////////////////////////////////////////////////////////
868
870{
871 Int_t nevt = other.numEntries() ;
872 reserve(nevt + numEntries());
873 for (int i=0 ; i<nevt ; i++) {
874 _vars.assign(*other.get(i)) ;
875 if (_wgtVar) {
876 _wgtVar->setVal(other.weight()) ;
877 }
878
879 fill() ;
880 }
881}
882
883
884
885////////////////////////////////////////////////////////////////////////////////
886
888{
890
891 for (auto elm : _realStoreList) {
892 elm->reset() ;
893 }
894
895 for (auto elm : _realfStoreList) {
896 elm->reset() ;
897 }
898
899 for (auto elm : _catStoreList) {
900 elm->reset() ;
901 }
902
903}
904
905////////////////////////////////////////////////////////////////////////////////
906/// Cache given RooAbsArgs: The tree is
907/// given direct write access of the args internal cache
908/// the args values is pre-calculated for all data points
909/// in this data collection. Upon a get() call, the
910/// internal cache of 'newVar' will be loaded with the
911/// precalculated value and it's dirty flag will be cleared.
912
913void RooVectorDataStore::cacheArgs(const RooAbsArg* owner, RooArgSet& newVarSet, const RooArgSet* nset, Bool_t skipZeroWeights)
914{
915 // Delete previous cache, if any
916 delete _cache ;
917 _cache = 0 ;
918
919 // Reorder cached elements. First constant nodes, then tracked nodes in order of dependence
920
921 // Step 1 - split in constant and tracked
922 RooArgSet newVarSetCopy(newVarSet);
923 RooArgSet orderedArgs;
924 vector<RooAbsArg*> trackArgs;
925 for (const auto arg : newVarSetCopy) {
926 if (arg->getAttribute("ConstantExpression") && !arg->getAttribute("NOCacheAndTrack")) {
927 orderedArgs.add(*arg) ;
928 } else {
929
930 // Explicitly check that arg depends on any of the observables, if this
931 // is not the case, skip it, as inclusion would result in repeated
932 // calculation of a function that has the same value for every event
933 // in the likelihood
934 if (arg->dependsOn(_vars) && !arg->getAttribute("NOCacheAndTrack")) {
935 trackArgs.push_back(arg) ;
936 } else {
937 newVarSet.remove(*arg) ;
938 }
939 }
940 }
941
942 // Step 2 - reorder tracked nodes
943 std::sort(trackArgs.begin(), trackArgs.end(), [](RooAbsArg* left, RooAbsArg* right){
944 //LM: exclude same comparison. This avoids an issue when using sort in MacOS versions
945 if (left == right) return false;
946 return right->dependsOn(*left);
947 });
948
949 // Step 3 - put back together
950 for (const auto trackedArg : trackArgs) {
951 orderedArgs.add(*trackedArg);
952 }
953
954 // WVE need to prune tracking entries _below_ constant nodes as the're not needed
955// cout << "Number of Cache-and-Tracked args are " << trackArgs.size() << endl ;
956// cout << "Compound ordered cache parameters = " << endl ;
957// orderedArgs.Print("v") ;
958
959 checkInit() ;
960
961 std::vector<RooArgSet*> vlist;
962 RooArgList cloneSet;
963
964 for (const auto var : orderedArgs) {
965
966 // Clone variable and attach to cloned tree
967 RooArgSet* newVarCloneList = (RooArgSet*) RooArgSet(*var).snapshot() ;
968 RooAbsArg* newVarClone = newVarCloneList->find(var->GetName()) ;
970
971 vlist.push_back(newVarCloneList) ;
972 cloneSet.add(*newVarClone) ;
973 }
974
975 _cacheOwner = (RooAbsArg*) owner ;
976 RooVectorDataStore* newCache = new RooVectorDataStore("cache","cache",orderedArgs) ;
977
978
980
981 std::vector<RooArgSet*> nsetList ;
982 std::vector<RooArgSet*> argObsList ;
983
984 // Now need to attach branch buffers of clones
985 for (const auto arg : cloneSet) {
986 arg->attachToVStore(*newCache) ;
987
988 RooArgSet* argObs = nset ? arg->getObservables(*nset) : arg->getVariables() ;
989 argObsList.push_back(argObs) ;
990
991 RooArgSet* normSet(0) ;
992 const char* catNset = arg->getStringAttribute("CATNormSet") ;
993 if (catNset) {
994// cout << "RooVectorDataStore::cacheArgs() cached node " << arg->GetName() << " has a normalization set specification CATNormSet = " << catNset << endl ;
995
996 RooArgSet anset = RooHelpers::selectFromArgSet(nset ? *nset : RooArgSet{}, catNset);
997 normSet = (RooArgSet*) anset.selectCommon(*argObs) ;
998
999 }
1000 const char* catCset = arg->getStringAttribute("CATCondSet") ;
1001 if (catCset) {
1002// cout << "RooVectorDataStore::cacheArgs() cached node " << arg->GetName() << " has a conditional observable set specification CATCondSet = " << catCset << endl ;
1003
1004 RooArgSet acset = RooHelpers::selectFromArgSet(nset ? *nset : RooArgSet{}, catCset);
1005 argObs->remove(acset,kTRUE,kTRUE) ;
1006 normSet = argObs ;
1007 }
1008
1009 // now construct normalization set for component from cset/nset spec
1010// if (normSet) {
1011// cout << "RooVectorDaraStore::cacheArgs() component " << arg->GetName() << " has custom normalization set " << *normSet << endl ;
1012// }
1013 nsetList.push_back(normSet) ;
1014 }
1015
1016
1017 // Fill values of of placeholder
1018 const std::size_t numEvt = size();
1019 newCache->reserve(numEvt);
1020 for (std::size_t i=0; i < numEvt; i++) {
1021 getNative(i) ;
1022 if (weight()!=0 || !skipZeroWeights) {
1023 for (unsigned int j = 0; j < cloneSet.size(); ++j) {
1024 auto& cloneArg = cloneSet[j];
1025 auto argNSet = nsetList[j];
1026 // WVE need to intervene here for condobs from ProdPdf
1027 cloneArg.syncCache(argNSet ? argNSet : nset) ;
1028 }
1029 }
1030 newCache->fill() ;
1031 }
1032
1034
1035
1036 // Now need to attach branch buffers of original function objects
1037 for (const auto arg : orderedArgs) {
1038 arg->attachToVStore(*newCache) ;
1039
1040 // Activate change tracking mode, if requested
1041 if (!arg->getAttribute("ConstantExpression") && dynamic_cast<RooAbsReal*>(arg)) {
1042 RealVector* rv = newCache->addReal((RooAbsReal*)arg) ;
1043 RooArgSet* deps = arg->getParameters(_vars) ;
1044 rv->setDependents(*deps) ;
1045
1046 // WV lookup normalization set and associate with RealVector
1047 // find ordinal number of arg in original list
1048 Int_t idx = cloneSet.index(arg->GetName()) ;
1049
1050 coutI(Optimization) << "RooVectorDataStore::cacheArg() element " << arg->GetName() << " has change tracking enabled on parameters " << *deps << endl ;
1051 rv->setNset(nsetList[idx]) ;
1052 delete deps ;
1053 }
1054
1055 }
1056
1057
1058 for (auto set : vlist) {
1059 delete set;
1060 }
1061 for (auto set : argObsList) {
1062 delete set;
1063 }
1064
1065 _cache = newCache ;
1067}
1068
1069
1071{
1072 if (_cache) _forcedUpdate = kTRUE ;
1073}
1074
1075
1076
1077////////////////////////////////////////////////////////////////////////////////
1078
1079void RooVectorDataStore::recalculateCache( const RooArgSet *projectedArgs, Int_t firstEvent, Int_t lastEvent, Int_t stepSize, Bool_t skipZeroWeights)
1080{
1081 if (!_cache) return ;
1082
1083 std::vector<RooVectorDataStore::RealVector *> tv;
1084 tv.reserve(static_cast<std::size_t>(_cache->_realStoreList.size() * 0.7)); // Typically, 30..60% need to be recalculated
1085
1086 // Check which items need recalculation
1087 for (const auto realVec : _cache->_realStoreList) {
1088 if (_forcedUpdate || realVec->needRecalc()) {
1089 tv.push_back(realVec);
1090 realVec->_nativeReal->setOperMode(RooAbsArg::ADirty);
1091 realVec->_nativeReal->_operMode = RooAbsArg::Auto;
1092 }
1093 }
1095
1096 // If no recalculations are needed stop here
1097 if (tv.empty()) {
1098 return;
1099 }
1100
1101
1102 // Refill caches of elements that require recalculation
1103 RooArgSet* ownedNset = 0 ;
1104 RooArgSet* usedNset = 0 ;
1105 if (projectedArgs && projectedArgs->getSize()>0) {
1106 ownedNset = (RooArgSet*) _vars.snapshot(kFALSE) ;
1107 ownedNset->remove(*projectedArgs,kFALSE,kTRUE);
1108 usedNset = ownedNset ;
1109 } else {
1110 usedNset = &_vars ;
1111 }
1112
1113
1114 for (int i=firstEvent ; i<lastEvent ; i+=stepSize) {
1115 get(i) ;
1116 Bool_t zeroWeight = (weight()==0) ;
1117 if (!zeroWeight || !skipZeroWeights) {
1118 for (auto realVector : tv) {
1119 realVector->_nativeReal->_valueDirty = kTRUE;
1120 realVector->_nativeReal->getValV(realVector->_nset ? realVector->_nset : usedNset);
1121 realVector->write(i);
1122 }
1123 }
1124 }
1125
1126 for (auto realVector : tv) {
1127 realVector->_nativeReal->setOperMode(RooAbsArg::AClean);
1128 }
1129
1130 delete ownedNset ;
1131
1132}
1133
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// Initialize cache of dataset: attach variables of cache ArgSet
1137/// to the corresponding TTree branches
1138
1139void RooVectorDataStore::attachCache(const RooAbsArg* newOwner, const RooArgSet& cachedVarsIn)
1140{
1141 // Only applicable if a cache exists
1142 if (!_cache) return ;
1143
1144 // Clone ctor, must connect internal storage to given new external set of vars
1145 std::vector<RealVector*> cacheElements(_cache->realStoreList());
1146 cacheElements.insert(cacheElements.end(), _cache->_realfStoreList.begin(), _cache->_realfStoreList.end());
1147
1148 for (const auto elm : cacheElements) {
1149 auto real = static_cast<RooAbsReal*>(cachedVarsIn.find(elm->bufArg()->GetName()));
1150 if (real) {
1151 // Adjust buffer pointer
1152 real->attachToVStore(*_cache) ;
1153 }
1154 }
1155
1156 for (const auto catVec : _cache->_catStoreList) {
1157 auto cat = static_cast<RooAbsCategory*>(cachedVarsIn.find(catVec->bufArg()->GetName()));
1158 if (cat) {
1159 // Adjust buffer pointer
1160 cat->attachToVStore(*_cache) ;
1161 }
1162 }
1163
1164 _cacheOwner = (RooAbsArg*) newOwner ;
1165}
1166
1167
1168
1169
1170////////////////////////////////////////////////////////////////////////////////
1171
1173{
1174 delete _cache;
1175 _cache = nullptr;
1176 _cacheOwner = nullptr;
1177 return ;
1178}
1179
1180
1181
1182
1183
1184////////////////////////////////////////////////////////////////////////////////
1185/// Disabling of branches is (intentionally) not implemented in vector
1186/// data stores (as the doesn't result in a net saving of time)
1187
1188void RooVectorDataStore::setArgStatus(const RooArgSet& /*set*/, Bool_t /*active*/)
1189{
1190 return ;
1191}
1192
1193
1194
1195
1196////////////////////////////////////////////////////////////////////////////////
1197
1199{
1200 for (auto arg : _varsww) {
1201 RooAbsArg* extArg = extObs.find(arg->GetName()) ;
1202 if (extArg) {
1203 extArg->attachToVStore(*this) ;
1204 }
1205 }
1206}
1207
1208
1209
1210////////////////////////////////////////////////////////////////////////////////
1211
1213{
1214 for (auto arg : _varsww) {
1215 arg->attachToVStore(*this);
1216 }
1217}
1218
1219
1220
1221////////////////////////////////////////////////////////////////////////////////
1222
1224{
1225 cout << "RooVectorDataStor::dump()" << endl ;
1226
1227 cout << "_varsww = " << endl ; _varsww.Print("v") ;
1228 cout << "realVector list is" << endl ;
1229
1230 for (const auto elm : _realStoreList) {
1231 cout << "RealVector " << elm << " _nativeReal = " << elm->_nativeReal << " = " << elm->_nativeReal->GetName() << " bufptr = " << elm->_buf << endl ;
1232 cout << " values : " ;
1233 Int_t imax = elm->_vec.size()>10 ? 10 : elm->_vec.size() ;
1234 for (Int_t i=0 ; i<imax ; i++) {
1235 cout << elm->_vec[i] << " " ;
1236 }
1237 cout << endl ;
1238 }
1239
1240 for (const auto elm : _realfStoreList) {
1241 cout << "RealFullVector " << elm << " _nativeReal = " << elm->_nativeReal << " = " << elm->_nativeReal->GetName()
1242 << " bufptr = " << elm->_buf << " errbufptr = " << elm->_bufE << endl ;
1243
1244 cout << " values : " ;
1245 Int_t imax = elm->_vec.size()>10 ? 10 : elm->_vec.size() ;
1246 for (Int_t i=0 ; i<imax ; i++) {
1247 cout << elm->_vec[i] << " " ;
1248 }
1249 cout << endl ;
1250 if (elm->_vecE) {
1251 cout << " errors : " ;
1252 for (Int_t i=0 ; i<imax ; i++) {
1253 cout << (*elm->_vecE)[i] << " " ;
1254 }
1255 cout << endl ;
1256
1257 }
1258 }
1259}
1260
1261
1262////////////////////////////////////////////////////////////////////////////////
1263/// Stream an object of class RooVectorDataStore.
1264
1265void RooVectorDataStore::Streamer(TBuffer &R__b)
1266{
1267 if (R__b.IsReading()) {
1268 R__b.ReadClassBuffer(RooVectorDataStore::Class(),this);
1269
1270 for (auto elm : _realStoreList) {
1271 RooAbsArg* arg = _varsww.find(elm->_nativeReal->GetName()) ;
1272 arg->attachToVStore(*this) ;
1273 }
1274 for (auto elm : _realfStoreList) {
1275 RooAbsArg* arg = _varsww.find(elm->_nativeReal->GetName()) ;
1276 arg->attachToVStore(*this) ;
1277 }
1278 for (auto elm : _catStoreList) {
1279 RooAbsArg* arg = _varsww.find(elm->_cat->GetName()) ;
1280 arg->attachToVStore(*this) ;
1281 }
1282
1283 } else {
1284 R__b.WriteClassBuffer(RooVectorDataStore::Class(),this);
1285 }
1286}
1287
1288
1289////////////////////////////////////////////////////////////////////////////////
1290/// Stream an object of class RooVectorDataStore::RealFullVector.
1291
1292void RooVectorDataStore::RealFullVector::Streamer(TBuffer &R__b)
1293{
1294 if (R__b.IsReading()) {
1295 R__b.ReadClassBuffer(RooVectorDataStore::RealFullVector::Class(),this);
1296
1297 // WVE - It seems that ROOT persistence turns null pointers to vectors into pointers to null-sized vectors
1298 // Intervene here to remove those null-sized vectors and replace with null pointers to not break
1299 // assumptions made elsewhere in this class
1300 if (_vecE && _vecE->empty()) { delete _vecE ; _vecE = 0 ; }
1301 if (_vecEL && _vecEL->empty()) { delete _vecEL ; _vecEL = 0 ; }
1302 if (_vecEH && _vecEH->empty()) { delete _vecEH ; _vecEH = 0 ; }
1303 } else {
1304 R__b.WriteClassBuffer(RooVectorDataStore::RealFullVector::Class(),this);
1305 }
1306}
1307
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Return batches of the data columns for the requested events.
1311/// \param[in] first First event in the batches.
1312/// \param[in] len Number of events in batches.
1313/// \return Spans with the associated data.
1315 RooAbsData::RealSpans evalData;
1316
1317 auto emplace = [this,&evalData,first,len](const RealVector* realVec) {
1318 auto span = realVec->getRange(first, first + len);
1319 auto result = evalData.emplace(realVec->_nativeReal, span);
1320 if (result.second == false || result.first->second.size() != len) {
1321 const auto size = result.second ? result.first->second.size() : 0;
1322 coutE(DataHandling) << "A batch of data for '" << realVec->_nativeReal->GetName()
1323 << "' was requested from " << first << " to " << first+len
1324 << ", but only the events [" << first << ", " << first + size << ") are available." << std::endl;
1325 }
1326 if (realVec->_real) {
1327 // If a buffer is attached, i.e. we are ready to load into a RooAbsReal outside of our dataset,
1328 // we can directly map our spans to this real.
1329 evalData.emplace(realVec->_real, std::move(span));
1330 }
1331 };
1332
1333 for (const auto realVec : _realStoreList) {
1334 emplace(realVec);
1335 }
1336 for (const auto realVec : _realfStoreList) {
1337 emplace(realVec);
1338 }
1339
1340 if (_cache) {
1341 for (const auto realVec : _cache->_realStoreList) {
1342 emplace(realVec);
1343 }
1344 for (const auto realVec : _cache->_realfStoreList) {
1345 emplace(realVec);
1346 }
1347 }
1348
1349 return evalData;
1350}
1351
1352
1355
1356 auto emplace = [this,&evalData,first,len](const CatVector* catVec) {
1357 auto span = catVec->getRange(first, first + len);
1358 auto result = evalData.emplace(catVec->_cat, span);
1359 if (result.second == false || result.first->second.size() != len) {
1360 const auto size = result.second ? result.first->second.size() : 0;
1361 coutE(DataHandling) << "A batch of data for '" << catVec->_cat->GetName()
1362 << "' was requested from " << first << " to " << first+len
1363 << ", but only the events [" << first << ", " << first + size << ") are available." << std::endl;
1364 }
1365 };
1366
1367 for (const auto& catVec : _catStoreList) {
1368 emplace(catVec);
1369 }
1370
1371 return evalData;
1372}
1373
1374
1375////////////////////////////////////////////////////////////////////////////////
1376/// Return the weights of all events in the range [first, first+len).
1377/// If an array with weights is stored, a batch with these weights will be returned. If
1378/// no weights are stored, an empty batch is returned. Use weight() to check if there's
1379/// a constant weight.
1381{
1382 if (_extWgtArray) {
1384 }
1385
1386 if (_wgtVar) {
1387 auto findWeightVar = [this](const RealVector* realVec) {
1388 return realVec->_nativeReal == _wgtVar || realVec->_nativeReal->GetName() == _wgtVar->GetName();
1389 };
1390
1391 auto storageIter = std::find_if(_realStoreList.begin(), _realStoreList.end(), findWeightVar);
1392 if (storageIter != _realStoreList.end())
1393 return (*storageIter)->getRange(first, first + len);
1394
1395 auto fstorageIter = std::find_if(_realfStoreList.begin(), _realfStoreList.end(), findWeightVar);
1396 if (fstorageIter != _realfStoreList.end())
1397 return (*fstorageIter)->getRange(first, first + len);
1398
1399 throw std::logic_error("RooVectorDataStore::getWeightBatch(): Could not retrieve data for _wgtVar.");
1400 }
1401 return {};
1402}
1403
1404
1406
1407 // First try a match by name
1408 for (auto catVec : _catStoreList) {
1409 if (std::string(catVec->bufArg()->GetName())==cat->GetName()) {
1410 return catVec;
1411 }
1412 }
1413
1414 // If nothing found this will make an entry
1415 _catStoreList.push_back(new CatVector(cat)) ;
1416
1417 return _catStoreList.back() ;
1418}
1419
1420
1422
1423 // First try a match by name
1424 for (auto realVec : _realStoreList) {
1425 if (realVec->bufArg()->namePtr()==real->namePtr()) {
1426 return realVec;
1427 }
1428 }
1429
1430 // Then check if an entry already exists for a full real
1431 for (auto fullVec : _realfStoreList) {
1432 if (fullVec->bufArg()->namePtr()==real->namePtr()) {
1433 // Return full vector as RealVector base class here
1434 return fullVec;
1435 }
1436 }
1437
1438 // If nothing found this will make an entry
1439 _realStoreList.push_back(new RealVector(real)) ;
1440
1441 return _realStoreList.back() ;
1442}
1443
1444
1446
1447 // First try a match by name
1448 for (auto fullVec : _realfStoreList) {
1449 if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
1450 return kTRUE ;
1451 }
1452 }
1453 return kFALSE ;
1454}
1455
1456
1458
1459 // First try a match by name
1460 for (auto fullVec : _realfStoreList) {
1461 if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
1462 return fullVec->_vecE ? kTRUE : kFALSE ;
1463 }
1464 }
1465 return kFALSE ;
1466}
1467
1468
1470
1471 // First try a match by name
1472 for (auto fullVec : _realfStoreList) {
1473 if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
1474 return fullVec->_vecEL ? kTRUE : kFALSE ;
1475 }
1476 }
1477 return kFALSE ;
1478}
1479
1480
1482
1483 // First try a match by name
1484 for (auto fullVec : _realfStoreList) {
1485 if (std::string(fullVec->bufArg()->GetName())==real->GetName()) {
1486 return fullVec;
1487 }
1488 }
1489
1490 // Then check if an entry already exists for a bare real
1491 for (auto realVec : _realStoreList) {
1492 if (std::string(realVec->bufArg()->GetName())==real->GetName()) {
1493
1494 // Convert element to full and add to full list
1495 _realfStoreList.push_back(new RealFullVector(*realVec,real)) ;
1496
1497 // Delete bare element
1498 _realStoreList.erase(std::find(_realStoreList.begin(), _realStoreList.end(), realVec));
1499 delete realVec;
1500
1501 return _realfStoreList.back() ;
1502 }
1503 }
1504
1505 // If nothing found this will make an entry
1506 _realfStoreList.push_back(new RealFullVector(real)) ;
1507
1508 return _realfStoreList.back() ;
1509}
1510
1511
1512/// Trigger a recomputation of the cached weight sums. Meant for use by RooFit
1513/// dataset converter functions such as the NumPy converter functions
1514/// implemented as pythonizations.
1516 double const* arr = nullptr;
1517 if (_extWgtArray) {
1518 arr = _extWgtArray;
1519 }
1520 if (_wgtVar) {
1521 const std::string wgtName = _wgtVar->GetName();
1522 for(auto const* real : _realStoreList) {
1523 if(wgtName == real->_nativeReal->GetName())
1524 arr = real->_vec.data();
1525 }
1526 for(auto const* real : _realfStoreList) {
1527 if(wgtName == real->_nativeReal->GetName())
1528 arr = real->_vec.data();
1529 }
1530 }
1531 if(arr == nullptr) {
1532 _sumWeight = size();
1533 return;
1534 }
1535 auto result = ROOT::Math::KahanSum<double, 4>::Accumulate(arr, arr + size(), 0.0);
1536 _sumWeight = result.Sum();
1537 _sumWeightCarry = result.Carry();
1538}
1539
1540
1541/// Exports all arrays in this RooVectorDataStore into a simple datastructure
1542/// to be used by RooFit internal export functions.
1544 ArraysStruct out;
1545 out.size = size();
1546
1547 for(auto const* real : _realStoreList) {
1548 out.reals.emplace_back(real->_nativeReal->GetName(), real->_vec.data());
1549 }
1550 for(auto const* realf : _realfStoreList) {
1551 std::string name = realf->_nativeReal->GetName();
1552 out.reals.emplace_back(name, realf->_vec.data());
1553 if(realf->_vecE) out.reals.emplace_back(name + "Err", realf->_vecE->data());
1554 if(realf->_vecEL) out.reals.emplace_back(name + "ErrLo", realf->_vecEL->data());
1555 if(realf->_vecEH) out.reals.emplace_back(name + "ErrHi", realf->_vecEH->data());
1556 }
1557 for(auto const* cat : _catStoreList) {
1558 out.cats.emplace_back(cat->_cat->GetName(), cat->_vec.data());
1559 }
1560
1561 if(_extWgtArray) out.reals.emplace_back("weight", _extWgtArray);
1562 if(_extWgtErrLoArray) out.reals.emplace_back("wgtErrLo", _extWgtErrLoArray);
1563 if(_extWgtErrHiArray) out.reals.emplace_back("wgtErrHi", _extWgtErrHiArray);
1564 if(_extSumW2Array) out.reals.emplace_back("sumW2",_extSumW2Array);
1565
1566 return out;
1567}
#define coutI(a)
#define coutE(a)
#define TRACE_DESTROY
Definition RooTrace.h:24
#define TRACE_CREATE
Definition RooTrace.h:23
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:101
const Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:364
char name[80]
Definition TGX11.cxx:110
#define hi
char * Form(const char *fmt,...)
static KahanSum< T, N > Accumulate(Iterator begin, Iterator end, T initialValue=T{})
Iterate over a range and return an instance of a KahanSum.
Definition Util.h:211
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
virtual RooAbsArg * cloneTree(const char *newname=0) const
Clone tree expression of objects.
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:577
void attachDataStore(const RooAbsDataStore &set)
Replace server nodes with names matching the dataset variable names with those data set variables,...
virtual void copyCache(const RooAbsArg *source, Bool_t valueOnly=kFALSE, Bool_t setValDirty=kTRUE)=0
static void setDirtyInhibit(Bool_t flag)
Control global dirty inhibit mode.
virtual Bool_t isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:239
virtual void syncCache(const RooArgSet *nset=0)=0
virtual void attachToVStore(RooVectorDataStore &vstore)=0
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
virtual RooAbsArg * createFundamental(const char *newname=0) const =0
Create a fundamental-type object that stores our type of value.
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.
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual void attachToVStore(RooVectorDataStore &vstore)
Attach the category index and label to as branches to the given vector store.
Storage_t const & get() const
Const access to the underlying stl container.
RooAbsCollection & assignValueOnly(const RooAbsCollection &other, bool forceIfSizeOne=false)
Sets the value of any argument in our set that also appears in the other set.
Int_t getSize() const
Int_t index(const RooAbsArg *arg) const
Returns index of given arg, or -1 if arg is not in the collection.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
Storage_t::size_type size() const
virtual void Print(Option_t *options=0) const
This method must be overridden when a class wants to print itself.
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...
const char * GetName() const
Returns name of object.
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.
RooAbsDataStore is the abstract base class for data collection that use a TTree as internal storage m...
virtual const RooArgSet * get(Int_t index) const =0
virtual void checkInit() const
virtual Double_t weight() const =0
virtual Int_t numEntries() const =0
std::map< RooFit::Detail::DataKey, RooSpan< const double > > RealSpans
Definition RooAbsData.h:159
std::map< RooFit::Detail::DataKey, RooSpan< const RooAbsCategory::value_type > > CategorySpans
Definition RooAbsData.h:160
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
virtual void attachToVStore(RooVectorDataStore &vstore)
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:94
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
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
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Bool_t getPoissonInterval(Int_t n, Double_t &mu1, Double_t &mu2, Double_t nSigma=1) const
Return a confidence interval for the expected number of events given n observed (unweighted) events.
static const RooHistError & instance()
Return a reference to a singleton object that is created the first time this method is called.
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:39
Double_t getAsymErrorLo() const
Definition RooRealVar.h:66
Bool_t hasAsymError(Bool_t allowZero=kTRUE) const
Definition RooRealVar.h:68
Double_t getAsymErrorHi() const
Definition RooRealVar.h:67
Bool_t hasError(Bool_t allowZero=kTRUE) const
Definition RooRealVar.h:63
Double_t getError() const
Definition RooRealVar.h:62
virtual void setVal(Double_t value)
Set value of variable to 'value'.
A simple container to hold a batch of data values.
Definition RooSpan.h:34
RooTreeDataStore is a TTree-backed data storage.
virtual const RooArgSet * get(Int_t index) const
Load the n-th data point (n='index') in memory and return a pointer to the internal RooArgSet holding...
RooArgSet _varsww
Was object constructed with default ctor?
virtual Int_t numEntries() const
void setNset(RooArgSet *newNset)
void setDependents(const RooArgSet &deps)
RooVectorDataStore uses std::vectors to store data columns.
const Double_t * _extWgtErrHiArray
External weight array - low error.
Bool_t hasAsymError(RooAbsReal *real)
virtual void resetCache() override
virtual Int_t numEntries() const override
virtual void attachCache(const RooAbsArg *newOwner, const RooArgSet &cachedVars) override
Initialize cache of dataset: attach variables of cache ArgSet to the corresponding TTree branches.
std::vector< RealFullVector * > _realfStoreList
Bool_t isFullReal(RooAbsReal *real)
RooVectorDataStore * _cache
virtual void resetBuffers() override
RooRealVar * weightVar(const RooArgSet &allVars, const char *wgtName)
Utility function for constructors Return pointer to weight variable if it is defined.
std::vector< RealVector * > _realStoreList
CatVector * addCategory(RooAbsCategory *cat)
virtual RooArgSet * addColumns(const RooArgList &varList) override
Utility function to add multiple columns in one call See addColumn() for details.
void loadValues(const RooAbsDataStore *tds, const RooFormulaVar *select=0, const char *rangeName=0, std::size_t nStart=0, std::size_t nStop=std::numeric_limits< std::size_t >::max()) override
virtual const RooArgSet * get(Int_t index) const override
Load the n-th data point (n='index') into the variables of this dataset, and return a pointer to the ...
virtual Bool_t changeObservableName(const char *from, const char *to) override
RealFullVector * addRealFull(RooAbsReal *real)
const Double_t * _extWgtErrLoArray
External weight array.
RooAbsData::RealSpans getBatches(std::size_t first, std::size_t len) const override
Return batches of the data columns for the requested events.
ULong64_t _currentWeightIndex
External sum of weights array.
virtual const RooArgSet * getNative(Int_t index) const
Load the n-th data point (n='index') into the variables of this dataset, and return a pointer to the ...
Double_t weight() const override
Return the weight of the last-retrieved data point.
virtual Int_t fill() override
Interface function to TTree::Fill.
virtual void append(RooAbsDataStore &other) override
std::vector< CatVector * > _catStoreList
Bool_t _forcedUpdate
Cache owner.
const Double_t * _extSumW2Array
External weight array - high error.
virtual void reset() override
virtual void attachBuffers(const RooArgSet &extObs) override
ArraysStruct getArrays() const
Exports all arrays in this RooVectorDataStore into a simple datastructure to be used by RooFit intern...
virtual void setDirtyProp(Bool_t flag) override
RooAbsData::CategorySpans getCategoryBatches(std::size_t, std::size_t len) const override
RooAbsDataStore * merge(const RooArgSet &allvars, std::list< RooAbsDataStore * > dstoreList) override
Merge columns of supplied data set(s) with this data set.
virtual void cacheArgs(const RooAbsArg *owner, RooArgSet &varSet, const RooArgSet *nset=0, Bool_t skipZeroWeights=kTRUE) override
Cache given RooAbsArgs: The tree is given direct write access of the args internal cache the args val...
RealVector * addReal(RooAbsReal *real)
virtual Double_t weightError(RooAbsData::ErrorType etype=RooAbsData::Poisson) const override
Return the error of the current weight.
void forceCacheUpdate() override
void recomputeSumWeight()
Trigger a recomputation of the cached weight sums.
std::vector< RealVector * > & realStoreList()
virtual void recalculateCache(const RooArgSet *, Int_t firstEvent, Int_t lastEvent, Int_t stepSize, Bool_t skipZeroWeights) override
std::size_t size() const
Get size of stored dataset.
Bool_t hasError(RooAbsReal *real)
RooSpan< const double > getWeightBatch(std::size_t first, std::size_t len) const override
Return the weights of all events in the range [first, first+len).
virtual const RooArgSet * get() const
virtual ~RooVectorDataStore()
Destructor.
RooArgSet varsNoWeight(const RooArgSet &allVars, const char *wgtName)
Utility function for constructors Return RooArgSet that is copy of allVars minus variable matching wg...
const Double_t * _extWgtArray
virtual RooAbsArg * addColumn(RooAbsArg &var, Bool_t adjustRange=kTRUE) override
Add a new column to the data set which holds the pre-calculated values of 'newVar'.
virtual void setArgStatus(const RooArgSet &set, Bool_t active) override
Disabling of branches is (intentionally) not implemented in vector data stores (as the doesn't result...
RooAbsArg * _cacheOwner
Optimization cache.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
A doubly linked list.
Definition TList.h:38
virtual void Add(TObject *obj)
Definition TList.h:81
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Double_t y[n]
Definition legend1.C:17
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
RooArgSet selectFromArgSet(RooArgSet const &, std::string const &names)
Construct a RooArgSet of objects in a RooArgSet whose names match to those in the names string.
Definition first.py:1
Output struct for the RooVectorDataStore::getArrays() helper function.
std::vector< ArrayInfo< double > > reals
std::vector< ArrayInfo< RooAbsCategory::value_type > > cats