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