Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooTreeDataStore.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 RooTreeDataStore.cxx
19\class RooTreeDataStore
20\ingroup Roofitcore
21
22TTree-backed data storage. When a file is opened before
23creating the data storage, the storage will be file-backed. This reduces memory
24pressure because it allows storing the data in the file and reading it on demand.
25For a completely memory-backed storage, which is faster than the file-backed storage,
26RooVectorDataStore can be used.
27
28With tree-backed storage, the tree can be found in the file with the name
29`RooTreeDataStore_name_title` for a dataset created as
30`RooDataSet("name", "title", ...)`.
31
32\note A file needs to be opened **before** creating the data storage to enable file-backed
33storage.
34```
35TFile outputFile("filename.root", "RECREATE");
36RooAbsData::setDefaultStorageType(RooAbsData::Tree);
37RooDataSet mydata(...);
38```
39
40One can also change between TTree- and std::vector-backed storage using
41RooAbsData::convertToTreeStore() and
42RooAbsData::convertToVectorStore().
43**/
44
45#include "RooTreeDataStore.h"
46
47#include "RooMsgService.h"
48#include "RooFormulaVar.h"
49#include "RooRealVar.h"
50#include "RooHistError.h"
51
52#include "ROOT/StringUtils.hxx"
53
54#include "TTree.h"
55#include "TFile.h"
56#include "TChain.h"
57#include "TDirectory.h"
58#include "TBuffer.h"
59#include "TBranch.h"
60#include "TROOT.h"
61
62#include <iomanip>
63using std::endl, std::list, std::string;
64
65
66
68
69
70
71////////////////////////////////////////////////////////////////////////////////
72
74
75
76
77////////////////////////////////////////////////////////////////////////////////
78/// Constructor to facilitate reading of legacy RooDataSets
79
81 RooAbsDataStore("blah","blah",varsNoWeight(vars,wgtVarName)),
82 _tree(t),
83 _defCtor(true),
84 _varsww(vars),
85 _wgtVar(weightVar(vars,wgtVarName))
86{
87}
88
89
90
91
92////////////////////////////////////////////////////////////////////////////////
93
95 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
96 _varsww(vars),
97 _wgtVar(weightVar(vars,wgtVarName))
98{
99 initialize() ;
100}
101
102
103////////////////////////////////////////////////////////////////////////////////
104
106 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
107 _varsww(vars),
108 _wgtVar(weightVar(vars,wgtVarName))
109{
110 initialize() ;
111
112 if (selExpr && *selExpr) {
113 // Create a RooFormulaVar cut from given cut expression
114 RooFormulaVar select(selExpr, selExpr, _vars, /*checkVariables=*/false);
115 loadValues(&t,&select);
116 } else {
117 loadValues(&t);
118 }
119}
120
121
122////////////////////////////////////////////////////////////////////////////////
123
125 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
126 _varsww(vars),
127 _wgtVar(weightVar(vars,wgtVarName))
128{
129 initialize() ;
130
131 if (selExpr && *selExpr) {
132 // Create a RooFormulaVar cut from given cut expression
133 RooFormulaVar select(selExpr, selExpr, _vars, /*checkVariables=*/false);
135 } else {
136 loadValues(&ads);
137 }
138}
139
140
141
142
143////////////////////////////////////////////////////////////////////////////////
144
146 const RooFormulaVar *cutVar, const char *cutRange, Int_t nStart, Int_t nStop,
147 const char *wgtVarName)
148 : RooAbsDataStore(name, title, varsNoWeight(vars, wgtVarName)),
149 _varsww(vars),
150 _wgtVar(weightVar(vars, wgtVarName))
151{
152 // WVE NEED TO ADJUST THIS FOR WEIGHTS
153
154 // Protected constructor for internal use only
155
156 createTree(makeTreeName(), title);
157
158 // Deep clone cutVar and attach clone to this dataset
159 std::unique_ptr<RooFormulaVar> cloneVar;
160 if (cutVar) {
161 cloneVar.reset(static_cast<RooFormulaVar*>(cutVar->cloneTree()));
162 cloneVar->attachDataStore(tds) ;
163 }
164
165 // Constructor from existing data set with list of variables that preserves the cache
166 initialize();
167
168 attachCache(nullptr,(static_cast<RooTreeDataStore&>(tds))._cachedVars) ;
169
170 // WVE copy values of cached variables here!!!
172 _cacheOwner = nullptr ;
173
174 loadValues(&tds,cloneVar.get(),cutRange,nStart,nStop);
175}
176
177
178std::unique_ptr<RooAbsDataStore> RooTreeDataStore::reduce(RooStringView name, RooStringView title,
179 const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
180 std::size_t nStart, std::size_t nStop) {
181 RooArgSet tmp(vars) ;
182 if(_wgtVar && !tmp.contains(*_wgtVar)) {
183 tmp.add(*_wgtVar) ;
184 }
185 const char* wgtVarName = _wgtVar ? _wgtVar->GetName() : nullptr;
186 return std::make_unique<RooTreeDataStore>(name, title, *this, tmp, cutVar, cutRange, nStart, nStop, wgtVarName);
187}
188
189
190////////////////////////////////////////////////////////////////////////////////
191/// Utility function for constructors
192/// Return RooArgSet that is copy of allVars minus variable matching wgtName if specified
193
195{
196 RooArgSet ret(allVars) ;
197 if(wgtName) {
198 RooAbsArg* wgt = allVars.find(wgtName) ;
199 if (wgt) {
200 ret.remove(*wgt,true,true) ;
201 }
202 }
203 return ret ;
204}
205
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Utility function for constructors
210/// Return pointer to weight variable if it is defined
211
213{
214 if(wgtName) {
215 RooRealVar* wgt = dynamic_cast<RooRealVar*>(allVars.find(wgtName)) ;
216 return wgt ;
217 }
218 return nullptr ;
219}
220
221
222
223
224////////////////////////////////////////////////////////////////////////////////
225/// Initialize cache of dataset: attach variables of cache ArgSet
226/// to the corresponding TTree branches
227
229{
230 // iterate over the cache variables for this dataset
232 for (RooAbsArg * var : cachedVarsIn) {
233 var->attachToTree(*_cacheTree,_defTreeBufSize) ;
234 _cachedVars.add(*var) ;
235 }
237
238}
239
240
241
242
243
244
245////////////////////////////////////////////////////////////////////////////////
246
249 _varsww(other._varsww),
250 _wgtVar(other._wgtVar),
251 _extWgtArray(other._extWgtArray),
252 _extWgtErrLoArray(other._extWgtErrLoArray),
253 _extWgtErrHiArray(other._extWgtErrHiArray),
254 _extSumW2Array(other._extSumW2Array),
255 _curWgt(other._curWgt),
256 _curWgtErrLo(other._curWgtErrLo),
257 _curWgtErrHi(other._curWgtErrHi),
258 _curWgtErr(other._curWgtErr)
259{
260 initialize() ;
261 loadValues(&other) ;
262}
263
264
265////////////////////////////////////////////////////////////////////////////////
266
268 RooAbsDataStore(other,varsNoWeight(vars,other._wgtVar?other._wgtVar->GetName():nullptr),newname),
269 _varsww(vars),
270 _wgtVar(other._wgtVar?weightVar(vars,other._wgtVar->GetName()):nullptr),
271 _extWgtArray(other._extWgtArray),
272 _extWgtErrLoArray(other._extWgtErrLoArray),
273 _extWgtErrHiArray(other._extWgtErrHiArray),
274 _extSumW2Array(other._extSumW2Array),
275 _curWgt(other._curWgt),
276 _curWgtErrLo(other._curWgtErrLo),
277 _curWgtErrHi(other._curWgtErrHi),
278 _curWgtErr(other._curWgtErr)
279{
280 initialize() ;
281 loadValues(&other) ;
282}
283
284
285
286
287////////////////////////////////////////////////////////////////////////////////
288/// Destructor
289
291{
292 if (_tree) {
293 delete _tree ;
294 }
295 if (_cacheTree) {
296 delete _cacheTree ;
297 }
298}
299
300
301
302////////////////////////////////////////////////////////////////////////////////
303/// One-time initialization common to all constructor forms. Attach
304/// variables of internal ArgSet to the corresponding TTree branches
305
307{
308 // Recreate (empty) cache tree
310
311 // Attach each variable to the dataset
312 for (auto var : _varsww) {
313 var->attachToTree(*_tree,_defTreeBufSize) ;
314 }
315}
316
317
318
319
320
321////////////////////////////////////////////////////////////////////////////////
322/// Create TTree object that lives in memory, independent of current
323/// location of gDirectory
324
326{
327 if (!_tree) {
328 _tree = new TTree(name.c_str(),title.c_str());
331 _tree->SetDirectory(nullptr);
332 }
333
334 TString pwd(gDirectory->GetPath()) ;
335 TString memDir(gROOT->GetName()) ;
336 memDir.Append(":/") ;
337 bool notInMemNow= (pwd!=memDir) ;
338
339 // std::cout << "RooTreeData::createTree pwd=" << pwd << " memDir=" << memDir << " notInMemNow = " << (notInMemNow?"T":"F") << std::endl ;
340
341 if (notInMemNow) {
342 gDirectory->cd(memDir) ;
343 }
344
345 if (!_cacheTree) {
346 _cacheTree = new TTree(TString{name.c_str()} + "_cacheTree", TString{title.c_str()});
347 _cacheTree->SetDirectory(nullptr) ;
348 gDirectory->RecursiveRemove(_cacheTree) ;
349 }
350
351 if (notInMemNow) {
352 gDirectory->cd(pwd) ;
353 }
354
355}
356
357
358
359
360////////////////////////////////////////////////////////////////////////////////
361/// Load values from tree 't' into this data collection, optionally
362/// selecting events using the RooFormulaVar 'select'.
363///
364/// The source tree 't' is cloned to not disturb its branch
365/// structure when retrieving information from it.
366void RooTreeDataStore::loadValues(const TTree *t, const RooFormulaVar* select, const char* /*rangeName*/, Int_t /*nStart*/, Int_t /*nStop*/)
367{
368 // Make our local copy of the tree, so we can safely loop through it.
369 // We need a custom deleter, because if we don't deregister the Tree from the directory
370 // of the original, it tears it down at destruction time!
371 auto deleter = [](TTree* tree){tree->SetDirectory(nullptr); delete tree;};
372 std::unique_ptr<TTree, decltype(deleter)> tClone(static_cast<TTree*>(t->Clone()), deleter);
373 tClone->SetDirectory(t->GetDirectory());
374
375 // Clone list of variables
378
379 // Check that we have the branches:
380 bool missingBranches = false;
381 for (const auto var : sourceArgSet) {
382 if (!tClone->GetBranch(var->GetName())) {
383 missingBranches = true;
384 coutE(InputArguments) << "Didn't find a branch in Tree '" << tClone->GetName() << "' to read variable '"
385 << var->GetName() << "' from."
386 << "\n\tNote: Name the RooFit variable the same as the branch." << std::endl;
387 }
388 }
389 if (missingBranches) {
390 coutE(InputArguments) << "Cannot import data from TTree '" << tClone->GetName()
391 << "' because some branches are missing !" << std::endl;
392 return;
393 }
394
395 // Attach args in cloned list to cloned source tree
396 for (const auto sourceArg : sourceArgSet) {
397 sourceArg->attachToTree(*tClone,_defTreeBufSize) ;
398 }
399
400 // Redirect formula servers to sourceArgSet
401 std::unique_ptr<RooFormulaVar> selectClone;
402 if (select) {
403 selectClone.reset( static_cast<RooFormulaVar*>(select->cloneTree()) );
404 selectClone->recursiveRedirectServers(sourceArgSet) ;
405 selectClone->setOperMode(RooAbsArg::ADirty,true) ;
406 }
407
408 // Loop over events in source tree
409 Int_t numInvalid(0) ;
410 const Long64_t nevent = tClone->GetEntries();
411 for(Long64_t i=0; i < nevent; ++i) {
412 const auto entryNumber = tClone->GetEntryNumber(i);
413 if (entryNumber<0) break;
414 tClone->GetEntry(entryNumber,1);
415
416 // Copy from source to destination
417 bool allOK(true) ;
418 for (unsigned int j=0; j < sourceArgSet.size(); ++j) {
419 auto destArg = _varsww[j];
420 const auto sourceArg = sourceArgSet[j];
421
422 destArg->copyCache(sourceArg) ;
423 sourceArg->copyCache(destArg) ;
424 if (!destArg->isValid()) {
425 numInvalid++ ;
426 allOK=false ;
427 if (numInvalid < 5) {
428 auto& log = coutI(DataHandling);
429 log << "RooTreeDataStore::loadValues(" << GetName() << ") Skipping event #" << i << " because " << destArg->GetName()
430 << " cannot accommodate the value ";
431 if(sourceArg->isCategory()) {
433 } else {
435 }
436 log << std::endl;
437 } else if (numInvalid == 5) {
438 coutI(DataHandling) << "RooTreeDataStore::loadValues(" << GetName() << ") Skipping ..." << std::endl;
439 }
440 break ;
441 }
442 }
443
444 // Does this event pass the cuts?
445 if (!allOK || (selectClone && selectClone->getVal()==0)) {
446 continue ;
447 }
448
449 fill() ;
450 }
451
452 if (numInvalid>0) {
453 coutW(DataHandling) << "RooTreeDataStore::loadValues(" << GetName() << ") Ignored " << numInvalid << " out-of-range events" << std::endl ;
454 }
455
456 SetTitle(t->GetTitle());
457}
458
459
460
461
462
463
464////////////////////////////////////////////////////////////////////////////////
465/// Load values from dataset 't' into this data collection, optionally
466/// selecting events using 'select' RooFormulaVar
467///
468
470 const char* rangeName, std::size_t nStart, std::size_t nStop)
471{
472 // Redirect formula servers to source data row
473 std::unique_ptr<RooFormulaVar> selectClone;
474 if (select) {
475 selectClone.reset( static_cast<RooFormulaVar*>(select->cloneTree()) );
476 selectClone->recursiveRedirectServers(*ads->get()) ;
477 selectClone->setOperMode(RooAbsArg::ADirty,true) ;
478 }
479
480 // Force RDS internal initialization
481 ads->get(0) ;
482
483 // Loop over events in source tree
484 const auto numEntr = static_cast<std::size_t>(ads->numEntries());
485 std::size_t nevent = nStop < numEntr ? nStop : numEntr;
486
487 auto TDS = dynamic_cast<const RooTreeDataStore*>(ads) ;
488 if (TDS) {
489 const_cast<RooTreeDataStore*>(TDS)->resetBuffers();
490 }
491
492 std::vector<std::string> ranges;
493 if (rangeName) {
494 ranges = ROOT::Split(rangeName, ",");
495 }
496
497 for (auto i=nStart; i < nevent ; ++i) {
498 ads->get(i) ;
499
500 // Does this event pass the cuts?
501 if (selectClone && selectClone->getVal()==0) {
502 continue ;
503 }
504
505
506 if (TDS) {
507 _varsww.assignValueOnly(TDS->_varsww) ;
508 } else {
509 _varsww.assignValueOnly(*ads->get()) ;
510 }
511
512 // Check that all copied values are valid
513 bool allValid = true;
514 for (const auto arg : _varsww) {
515 allValid = arg->isValid() && (ranges.empty() || std::any_of(ranges.begin(), ranges.end(),
516 [arg](const std::string& range){return arg->inRange(range.c_str());}) );
517 if (!allValid)
518 break ;
519 }
520
521 if (!allValid) {
522 continue ;
523 }
524
525 _cachedVars.assign(static_cast<RooTreeDataStore const*>(ads)->_cachedVars) ;
526 fill() ;
527 }
528
529 if (TDS) {
530 const_cast<RooTreeDataStore*>(TDS)->restoreAlternateBuffers();
531 }
532
533 SetTitle(ads->GetTitle());
534}
535
536
537////////////////////////////////////////////////////////////////////////////////
538/// Interface function to TTree::Fill
539
541{
542 return _tree->Fill() ;
543}
544
545
546
547////////////////////////////////////////////////////////////////////////////////
548/// Load the n-th data point (n='index') in memory
549/// and return a pointer to the internal RooArgSet
550/// holding its coordinates.
551
553{
554 checkInit() ;
555
556 Int_t ret = const_cast<RooTreeDataStore*>(this)->GetEntry(index, 1);
557
558 if(!ret) return nullptr;
559
560 if (_doDirtyProp) {
561 // Raise all dirty flags
562 for (auto var : _vars) {
563 var->setValueDirty(); // This triggers recalculation of all clients
564 }
565
566 for (auto var : _cachedVars) {
567 var->setValueDirty(); // This triggers recalculation of all clients, but doesn't recalculate self
568 var->clearValueDirty();
569 }
570 }
571
572 // Update current weight cache
573 if (_extWgtArray) {
574
575 // If external array is specified use that
580
581 } else if (_wgtVar) {
582
583 // Otherwise look for weight variable
584 _curWgt = _wgtVar->getVal() ;
588
589 } else {
590
591 // Otherwise return 1
592 _curWgt=1.0 ;
593 _curWgtErrLo = 0 ;
594 _curWgtErrHi = 0 ;
595 _curWgtErr = 0 ;
596
597 }
598
599 return &_vars;
600}
601
602
603////////////////////////////////////////////////////////////////////////////////
604/// Return the weight of the n-th data point (n='index') in memory
605
607{
608 return _curWgt ;
609}
610
611
612////////////////////////////////////////////////////////////////////////////////
613
615{
616 if (_extWgtArray) {
617
618 // We have a weight array, use that info
619
620 // Return symmetric error on current bin calculated either from Poisson statistics or from SumOfWeights
621 double lo = 0;
622 double hi = 0;
623 weightError(lo,hi,etype) ;
624 return (lo+hi)/2 ;
625
626 } else if (_wgtVar) {
627
628 // We have a weight variable, use that info
629 if (_wgtVar->hasAsymError()) {
630 return ( _wgtVar->getAsymErrorHi() - _wgtVar->getAsymErrorLo() ) / 2 ;
631 } else {
632 return _wgtVar->getError() ;
633 }
634
635 }
636
637 // We have no weights
638 return 0.0;
639}
640
641
642
643////////////////////////////////////////////////////////////////////////////////
644
645void RooTreeDataStore::weightError(double& lo, double& hi, RooAbsData::ErrorType etype) const
646{
647 if (_extWgtArray) {
648
649 // We have a weight array, use that info
650 switch (etype) {
651
652 case RooAbsData::Auto:
653 throw string(Form("RooDataHist::weightError(%s) error type Auto not allowed here",GetName())) ;
654 break ;
655
657 throw string(Form("RooDataHist::weightError(%s) error type Expected not allowed here",GetName())) ;
658 break ;
659
661 // Weight may be preset or precalculated
662 if (_curWgtErrLo>=0) {
663 lo = _curWgtErrLo ;
664 hi = _curWgtErrHi ;
665 return ;
666 }
667
668 // Otherwise Calculate poisson errors
669 double ym;
670 double yp;
671 RooHistError::instance().getPoissonInterval(Int_t(weight()+0.5),ym,yp,1) ;
672 lo = weight()-ym ;
673 hi = yp-weight() ;
674 return ;
675
677 lo = _curWgtErr ;
678 hi = _curWgtErr ;
679 return ;
680
681 case RooAbsData::None:
682 lo = 0 ;
683 hi = 0 ;
684 return ;
685 }
686
687 } else if (_wgtVar) {
688
689 // We have a weight variable, use that info
690 if (_wgtVar->hasAsymError()) {
692 lo = _wgtVar->getAsymErrorLo() ;
693 } else {
694 hi = _wgtVar->getError() ;
695 lo = _wgtVar->getError() ;
696 }
697
698 } else {
699
700 // We are unweighted
701 lo=0 ;
702 hi=0 ;
703
704 }
705}
706
707
708////////////////////////////////////////////////////////////////////////////////
709/// Change name of internal observable named 'from' into 'to'
710
711bool RooTreeDataStore::changeObservableName(const char* from, const char* to)
712{
713 // Find observable to be changed
714 RooAbsArg* var = _vars.find(from) ;
715
716 // Check that we found it
717 if (!var) {
718 coutE(InputArguments) << "RooTreeDataStore::changeObservableName(" << GetName() << " no observable " << from << " in this dataset" << std::endl ;
719 return true ;
720 }
721
722 // Process name change
724 var->SetName(to) ;
725
726 // Change the branch name as well
727 if (_tree->GetBranch(oldBranchName.Data())) {
728
729 // Simple case varName = branchName
730 _tree->GetBranch(oldBranchName.Data())->SetName(var->cleanBranchName().Data()) ;
731
732 // Process any error branch if existing
733 if (_tree->GetBranch(Form("%s_err",oldBranchName.Data()))) {
734 _tree->GetBranch(Form("%s_err",oldBranchName.Data()))->SetName(Form("%s_err",var->cleanBranchName().Data())) ;
735 }
736 if (_tree->GetBranch(Form("%s_aerr_lo",oldBranchName.Data()))) {
737 _tree->GetBranch(Form("%s_aerr_lo",oldBranchName.Data()))->SetName(Form("%s_aerr_lo",var->cleanBranchName().Data())) ;
738 }
739 if (_tree->GetBranch(Form("%s_aerr_hi",oldBranchName.Data()))) {
740 _tree->GetBranch(Form("%s_aerr_hi",oldBranchName.Data()))->SetName(Form("%s_aerr_hi",var->cleanBranchName().Data())) ;
741 }
742
743 } else {
744
745 // Native category case branchNames = varName_idx and varName_lbl
746 if (_tree->GetBranch(Form("%s_idx",oldBranchName.Data()))) {
747 _tree->GetBranch(Form("%s_idx",oldBranchName.Data()))->SetName(Form("%s_idx",var->cleanBranchName().Data())) ;
748 }
749 if (_tree->GetBranch(Form("%s_lbl",oldBranchName.Data()))) {
750 _tree->GetBranch(Form("%s_lbl",oldBranchName.Data()))->SetName(Form("%s_lb",var->cleanBranchName().Data())) ;
751 }
752
753 }
754
755 return false ;
756}
757
758
759
760////////////////////////////////////////////////////////////////////////////////
761/// Add a new column to the data set which holds the pre-calculated values
762/// of 'newVar'. This operation is only meaningful if 'newVar' is a derived
763/// value.
764///
765/// The return value points to the added element holding 'newVar's value
766/// in the data collection. The element is always the corresponding fundamental
767/// type of 'newVar' (e.g. a RooRealVar if 'newVar' is a RooFormulaVar)
768///
769/// Note: This function is explicitly NOT intended as a speed optimization
770/// opportunity for the user. Components of complex PDFs that can be
771/// precalculated with the dataset are automatically identified as such
772/// and will be precalculated when fitting to a dataset
773///
774/// By forcibly precalculating functions with non-trivial Jacobians,
775/// or functions of multiple variables occurring in the data set,
776/// using addColumn(), you may alter the outcome of the fit.
777///
778/// Only in cases where such a modification of fit behaviour is intentional,
779/// this function should be used.
780
782{
783 checkInit() ;
784
785 // Create a fundamental object of the right type to hold newVar values
786 auto valHolder = std::unique_ptr<RooAbsArg>{newVar.createFundamental()}.release();
787 // Sanity check that the holder really is fundamental
788 if(!valHolder->isFundamental()) {
789 coutE(InputArguments) << GetName() << "::addColumn: holder argument is not fundamental: \""
790 << valHolder->GetName() << "\"" << std::endl;
791 return nullptr;
792 }
793
794 // WVE need to reset TTRee buffers to original datamembers here
795 resetBuffers() ;
796
797 // Clone variable and attach to cloned tree
798 std::unique_ptr<RooAbsArg> newVarClone{newVar.cloneTree()};
799 newVarClone->recursiveRedirectServers(_vars,false) ;
800
801 // Attach value place holder to this tree
802 ((RooAbsArg*)valHolder)->attachToTree(*_tree,_defTreeBufSize) ;
805
806
807 // Fill values of placeholder
808 for (int i=0 ; i<GetEntries() ; i++) {
809 get(i) ;
810
811 newVarClone->syncCache(&_vars) ;
812 valHolder->copyCache(newVarClone.get());
813 valHolder->fillTreeBranch(*_tree) ;
814 }
815
816 // WVE need to restore TTRee buffers to previous values here
818
819 if (adjustRange) {
820// // Set range of valHolder to (just) bracket all values stored in the dataset
821// double vlo,vhi ;
822// RooRealVar* rrvVal = dynamic_cast<RooRealVar*>(valHolder) ;
823// if (rrvVal) {
824// getRange(*rrvVal,vlo,vhi,0.05) ;
825// rrvVal->setRange(vlo,vhi) ;
826// }
827 }
828
829 return valHolder ;
830}
831
832
833////////////////////////////////////////////////////////////////////////////////
834/// Merge columns of supplied data set(s) with this data set. All
835/// data sets must have equal number of entries. In case of
836/// duplicate columns the column of the last dataset in the list
837/// prevails
838
840{
841 RooTreeDataStore* mergedStore = new RooTreeDataStore("merged","merged",allVars) ;
842
843 Int_t nevt = dstoreList.front()->numEntries() ;
844 for (int i=0 ; i<nevt ; i++) {
845
846 // Cope data from self
847 mergedStore->_vars.assign(*get(i)) ;
848
849 // Copy variables from merge sets
850 for (list<RooAbsDataStore*>::iterator iter = dstoreList.begin() ; iter!=dstoreList.end() ; ++iter) {
851 const RooArgSet* partSet = (*iter)->get(i) ;
852 mergedStore->_vars.assign(*partSet) ;
853 }
854
855 mergedStore->fill() ;
856 }
857 return mergedStore ;
858}
859
860
861
862
863
864////////////////////////////////////////////////////////////////////////////////
865
867{
868 Int_t nevt = other.numEntries() ;
869 for (int i=0 ; i<nevt ; i++) {
870 _vars.assign(*other.get(i)) ;
871 if (_wgtVar) {
872 _wgtVar->setVal(other.weight()) ;
873 }
874
875 fill() ;
876 }
877}
878
879
880////////////////////////////////////////////////////////////////////////////////
881
883{
884 if (_wgtVar) {
885
886 double sum(0);
887 double carry(0);
888 Int_t nevt = numEntries() ;
889 for (int i=0 ; i<nevt ; i++) {
890 get(i) ;
891 // Kahan's algorithm for summing to avoid loss of precision
892 double y = _wgtVar->getVal() - carry;
893 double t = sum + y;
894 carry = (t - sum) - y;
895 sum = t;
896 }
897 return sum ;
898
899 } else if (_extWgtArray) {
900
901 double sum(0);
902 double carry(0);
903 Int_t nevt = numEntries() ;
904 for (int i=0 ; i<nevt ; i++) {
905 // Kahan's algorithm for summing to avoid loss of precision
906 double y = _extWgtArray[i] - carry;
907 double t = sum + y;
908 carry = (t - sum) - y;
909 sum = t;
910 }
911 return sum ;
912
913 } else {
914
915 return numEntries() ;
916
917 }
918}
919
920
921
922
923////////////////////////////////////////////////////////////////////////////////
924
926{
927 return _tree->GetEntries() ;
928}
929
930
931
932////////////////////////////////////////////////////////////////////////////////
933
935{
936 Reset() ;
937}
938
939
940
941////////////////////////////////////////////////////////////////////////////////
942/// Cache given RooAbsArgs with this tree: The tree is
943/// given direct write access of the args internal cache
944/// the args values is pre-calculated for all data points
945/// in this data collection. Upon a get() call, the
946/// internal cache of 'newVar' will be loaded with the
947/// precalculated value and it's dirty flag will be cleared.
948
949void RooTreeDataStore::cacheArgs(const RooAbsArg* owner, RooArgSet& newVarSet, const RooArgSet* nset, bool /*skipZeroWeights*/)
950{
951 checkInit() ;
952
953 _cacheOwner = owner ;
954
955 std::unique_ptr<RooArgSet> constExprVarSet{newVarSet.selectByAttrib("ConstantExpression", true)};
956
957 bool doTreeFill = (_cachedVars.empty()) ;
958
959 for (RooAbsArg * arg : *constExprVarSet) {
960 // Attach original newVar to this tree
961 arg->attachToTree(*_cacheTree,_defTreeBufSize) ;
962 //arg->recursiveRedirectServers(_vars) ;
963 _cachedVars.add(*arg) ;
964 }
965
966 // WVE need to reset TTRee buffers to original datamembers here
967 //resetBuffers() ;
968
969 // Refill regular and cached variables of current tree from clone
970 for (int i=0 ; i<GetEntries() ; i++) {
971 get(i) ;
972
973 // Evaluate the cached variables and store the results
974 for (RooAbsArg * arg : *constExprVarSet) {
975 arg->setValueDirty() ;
976 arg->syncCache(nset) ;
977 if (!doTreeFill) {
978 arg->fillTreeBranch(*_cacheTree) ;
979 }
980 }
981
982 if (doTreeFill) {
983 _cacheTree->Fill() ;
984 }
985 }
986
987 // WVE need to restore TTRee buffers to previous values here
988 //restoreAlternateBuffers() ;
989}
990
991
992
993
994////////////////////////////////////////////////////////////////////////////////
995/// Activate or deactivate the branch status of the TTree branch associated
996/// with the given set of dataset observables
997
998void RooTreeDataStore::setArgStatus(const RooArgSet& set, bool active)
999{
1000 for (RooAbsArg * arg : set) {
1001 RooAbsArg* depArg = _vars.find(arg->GetName()) ;
1002 if (!depArg) {
1003 coutE(InputArguments) << "RooTreeDataStore::setArgStatus(" << GetName()
1004 << ") dataset doesn't contain variable " << arg->GetName() << std::endl ;
1005 continue ;
1006 }
1007 depArg->setTreeBranchStatus(*_tree,active) ;
1008 }
1009}
1010
1011
1012
1013////////////////////////////////////////////////////////////////////////////////
1014/// Remove tree with values of cached observables
1015/// and clear list of cached observables
1016
1018{
1019 // Empty list of cached functions
1021
1022 // Delete & recreate cache tree
1023 delete _cacheTree ;
1024 _cacheTree = nullptr ;
1025 createTree(makeTreeName().c_str(), GetTitle());
1026
1027 return ;
1028}
1029
1030
1031
1032
1033////////////////////////////////////////////////////////////////////////////////
1034
1036{
1038 for (const auto arg : _varsww) {
1039 RooAbsArg* extArg = extObs.find(arg->GetName()) ;
1040 if (extArg) {
1041 if (arg->getAttribute("StoreError")) {
1042 extArg->setAttribute("StoreError") ;
1043 }
1044 if (arg->getAttribute("StoreAsymError")) {
1045 extArg->setAttribute("StoreAsymError") ;
1046 }
1047 extArg->attachToTree(*_tree) ;
1049 }
1050 }
1051}
1052
1053
1054
1055////////////////////////////////////////////////////////////////////////////////
1056
1058{
1059 for(RooAbsArg * arg : _varsww) {
1060 arg->attachToTree(*_tree) ;
1061 }
1062}
1063
1064
1065
1066////////////////////////////////////////////////////////////////////////////////
1067
1069{
1070 for(RooAbsArg * arg : _attachedBuffers) {
1071 arg->attachToTree(*_tree) ;
1072 }
1073}
1074
1075
1076
1077////////////////////////////////////////////////////////////////////////////////
1078
1080{
1081 if (_defCtor) {
1082 const_cast<RooTreeDataStore*>(this)->initialize() ;
1083 _defCtor = false ;
1084 }
1085}
1086
1087
1088
1089
1090
1091////////////////////////////////////////////////////////////////////////////////
1092/// Interface function to TTree::GetEntries
1093
1095{
1096 return _tree->GetEntries() ;
1097}
1098
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Interface function to TTree::Reset
1102
1107
1108
1109////////////////////////////////////////////////////////////////////////////////
1110/// Interface function to TTree::Fill
1111
1113{
1114 return _tree->Fill() ;
1115}
1116
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Interface function to TTree::GetEntry
1120
1122{
1124 if (!ret1) return 0 ;
1126 return ret1 ;
1127}
1128
1129
1130////////////////////////////////////////////////////////////////////////////////
1131
1136
1137////////////////////////////////////////////////////////////////////////////////
1138/// Stream an object of class RooTreeDataStore.
1139
1141{
1142 if (R__b.IsReading()) {
1143 UInt_t R__s;
1144 UInt_t R__c;
1145 const Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1146
1147 R__b.ReadClassBuffer(RooTreeDataStore::Class(), this, R__v, R__s, R__c);
1148
1149 if (!_tree) {
1150 // If the tree has not been deserialised automatically, it is time to load
1151 // it now.
1152 TFile* parent = dynamic_cast<TFile*>(R__b.GetParent());
1153 assert(parent);
1154 parent->GetObject(makeTreeName().c_str(), _tree);
1155 }
1156
1157 initialize();
1158
1159 } else {
1160
1161 TTree* tmpTree = _tree;
1162 auto parent = dynamic_cast<TDirectory*>(R__b.GetParent());
1163 if (_tree && parent) {
1164 // Large trees cannot be written because of the 1Gb I/O limitation.
1165 // Here, we take the tree away from our instance, write it, and continue
1166 // to write the rest of the class normally
1167 auto tmpDir = _tree->GetDirectory();
1168
1169 _tree->SetDirectory(parent);
1170 _tree->FlushBaskets(false);
1171 parent->WriteObject(_tree, makeTreeName().c_str());
1173 _tree = nullptr;
1174 }
1175
1176 R__b.WriteClassBuffer(RooTreeDataStore::Class(), this);
1177
1178 _tree = tmpTree;
1179 }
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Generate a name for the storage tree from the name and title of this instance.
1185 std::string title = GetTitle();
1186 std::replace(title.begin(), title.end(), ' ', '_');
1187 std::replace(title.begin(), title.end(), '-', '_');
1188 return std::string("RooTreeDataStore_") + GetName() + "_" + title;
1189}
1190
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// Get the weights of the events in the range [first, first+len).
1194/// This implementation will fill a vector with every event retrieved one by one
1195/// (even if the weight is constant). Then, it returns a span.
1196std::span<const double> RooTreeDataStore::getWeightBatch(std::size_t first, std::size_t len) const {
1197
1198 if (_extWgtArray) {
1199 return {_extWgtArray + first, len};
1200 }
1201
1202 if (!_weightBuffer) {
1203 _weightBuffer = std::make_unique<std::vector<double>>();
1204 _weightBuffer->reserve(len);
1205
1206 for (std::size_t i = 0; i < GetEntries(); ++i) {
1207 _weightBuffer->push_back(weight(i));
1208 }
1209 }
1210
1211 return {_weightBuffer->data() + first, len};
1212}
#define coutI(a)
#define coutW(a)
#define coutE(a)
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
const char Option_t
Definition RtypesCore.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:384
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
#define hi
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
void SetName(const char *name) override
Set the name of the TNamed.
TString cleanBranchName() const
Construct a mangled name from the actual name that is free of any math symbols that might be interpre...
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
RooAbsCollection & assignValueOnly(const RooAbsCollection &other, bool forceIfSizeOne=false)
Sets the value of any argument in our set that also appears in the other set.
virtual bool add(const RooAbsArg &var, bool silent=false)
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...
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for a data collection.
bool _doDirtyProp
Switch do (de)activate dirty state propagation when loading a data point.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:159
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
static const RooHistError & instance()
Return a reference to a singleton object that is created the first time this method is called.
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
double getError() const
Definition RooRealVar.h:58
bool hasAsymError(bool allowZero=true) const
Definition RooRealVar.h:64
double getAsymErrorHi() const
Definition RooRealVar.h:63
double getAsymErrorLo() const
Definition RooRealVar.h:62
The RooStringView is a wrapper around a C-style string that can also be constructed from a std::strin...
const char * c_str() const
TTree-backed data storage.
void initialize()
One-time initialization common to all constructor forms.
double _curWgtErr
Weight of current event.
double weightError(RooAbsData::ErrorType etype=RooAbsData::Poisson) const override
void resetBuffers() override
double _curWgt
Buffer for weights in case a batch of values is requested.
void Draw(Option_t *option="") override
Default Draw method for all objects.
void attachCache(const RooAbsArg *newOwner, const RooArgSet &cachedVars) override
Initialize cache of dataset: attach variables of cache ArgSet to the corresponding TTree branches.
double _curWgtErrHi
Weight of current event.
static TClass * Class()
Int_t numEntries() const override
std::string makeTreeName() const
Generate a name for the storage tree from the name and title of this instance.
RooArgSet varsNoWeight(const RooArgSet &allVars, const char *wgtName=nullptr)
Utility function for constructors Return RooArgSet that is copy of allVars minus variable matching wg...
~RooTreeDataStore() override
Destructor.
void createTree(RooStringView name, RooStringView title)
Create TTree object that lives in memory, independent of current location of gDirectory.
const double * _extWgtErrHiArray
! External weight array - high error
Stat_t GetEntries() const
Interface function to TTree::GetEntries.
void attachBuffers(const RooArgSet &extObs) override
Int_t GetEntry(Int_t entry=0, Int_t getall=0)
Interface function to TTree::GetEntry.
void reset() override
RooAbsDataStore * merge(const RooArgSet &allvars, std::list< RooAbsDataStore * > dstoreList) override
Merge columns of supplied data set(s) with this data set.
static Int_t _defTreeBufSize
RooArgSet _attachedBuffers
! Currently attached buffers (if different from _varsww)
Int_t fill() override
Interface function to TTree::Fill.
double sumEntries() const override
std::unique_ptr< RooAbsDataStore > reduce(RooStringView name, RooStringView title, const RooArgSet &vars, const RooFormulaVar *cutVar, const char *cutRange, std::size_t nStart, std::size_t nStop) override
bool _defCtor
Object owning cache contents.
RooAbsArg * addColumn(RooAbsArg &var, bool adjustRange=true) override
Add a new column to the data set which holds the pre-calculated values of 'newVar'.
double weight() const override
Return the weight of the n-th data point (n='index') in memory.
void Reset(Option_t *option=nullptr)
Interface function to TTree::Reset.
void loadValues(const TTree *t, const RooFormulaVar *select=nullptr, const char *rangeName=nullptr, Int_t nStart=0, Int_t nStop=2000000000)
Load values from tree 't' into this data collection, optionally selecting events using the RooFormula...
void append(RooAbsDataStore &other) override
std::span< const double > getWeightBatch(std::size_t first, std::size_t len) const override
Get the weights of the events in the range [first, first+len).
const double * _extWgtErrLoArray
! External weight array - low error
void checkInit() const override
std::unique_ptr< std::vector< double > > _weightBuffer
Int_t Fill()
Interface function to TTree::Fill.
const double * _extSumW2Array
! External sum of weights array
void Streamer(TBuffer &) override
Stream an object of class RooTreeDataStore.
RooRealVar * weightVar(const RooArgSet &allVars, const char *wgtName=nullptr)
Utility function for constructors Return pointer to weight variable if it is defined.
const double * _extWgtArray
! External weight array
double _curWgtErrLo
Weight of current event.
bool changeObservableName(const char *from, const char *to) override
Change name of internal observable named 'from' into 'to'.
void resetCache() override
Remove tree with values of cached observables and clear list of cached observables.
void setArgStatus(const RooArgSet &set, bool active) override
Activate or deactivate the branch status of the TTree branch associated with the given set of dataset...
void cacheArgs(const RooAbsArg *owner, RooArgSet &varSet, const RooArgSet *nset=nullptr, bool skipZeroWeights=false) override
Cache given RooAbsArgs with this tree: The tree is given direct write access of the args internal cac...
virtual const RooArgSet * get() const
const RooAbsArg * _cacheOwner
TTree holding the cached function values.
RooArgSet _varsww
Was object constructed with default ctor?
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Describe directory structure in memory.
Definition TDirectory.h:45
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:212
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
void ResetBit(UInt_t f)
Definition TObject.h:198
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4596
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5287
virtual Int_t FlushBaskets(bool create_cluster=true) const
Write to disk all the basket that have not yet been individually written and create an event cluster ...
Definition TTree.cxx:5122
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition TTree.cxx:5631
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:431
TDirectory * GetDirectory() const
Definition TTree.h:462
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:8959
virtual Long64_t GetEntries() const
Definition TTree.h:463
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:7996
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="", bool needCopyAddresses=false)
Copy nentries from given tree to this tree.
Definition TTree.cxx:3527
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.
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345