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
80RooTreeDataStore::RooTreeDataStore(TTree* t, const RooArgSet& vars, const char* wgtVarName) :
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
94RooTreeDataStore::RooTreeDataStore(RooStringView name, RooStringView title, const RooArgSet& vars, const char* wgtVarName) :
95 RooAbsDataStore(name,title,varsNoWeight(vars,wgtVarName)),
96 _varsww(vars),
97 _wgtVar(weightVar(vars,wgtVarName))
98{
99 initialize() ;
100}
101
102
103////////////////////////////////////////////////////////////////////////////////
104
105RooTreeDataStore::RooTreeDataStore(RooStringView name, RooStringView title, const RooArgSet& vars, TTree& t, const char* selExpr, const char* wgtVarName) :
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
124RooTreeDataStore::RooTreeDataStore(RooStringView name, RooStringView title, const RooArgSet& vars, const RooAbsDataStore& ads, const char* selExpr, const char* wgtVarName) :
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);
134 loadValues(&ads,&select);
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 loadValues(&tds,cloneVar.get(),cutRange,nStart,nStop);
169}
170
171
172std::unique_ptr<RooAbsDataStore> RooTreeDataStore::reduce(RooStringView name, RooStringView title,
173 const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
174 std::size_t nStart, std::size_t nStop) {
175 RooArgSet tmp(vars) ;
176 if(_wgtVar && !tmp.contains(*_wgtVar)) {
177 tmp.add(*_wgtVar) ;
178 }
179 const char* wgtVarName = _wgtVar ? _wgtVar->GetName() : nullptr;
180 return std::make_unique<RooTreeDataStore>(name, title, *this, tmp, cutVar, cutRange, nStart, nStop, wgtVarName);
181}
182
183
184////////////////////////////////////////////////////////////////////////////////
185/// Utility function for constructors
186/// Return RooArgSet that is copy of allVars minus variable matching wgtName if specified
187
188RooArgSet RooTreeDataStore::varsNoWeight(const RooArgSet& allVars, const char* wgtName)
189{
190 RooArgSet ret(allVars) ;
191 if(wgtName) {
192 RooAbsArg* wgt = allVars.find(wgtName) ;
193 if (wgt) {
194 ret.remove(*wgt,true,true) ;
195 }
196 }
197 return ret ;
198}
199
200
201
202////////////////////////////////////////////////////////////////////////////////
203/// Utility function for constructors
204/// Return pointer to weight variable if it is defined
205
206RooRealVar* RooTreeDataStore::weightVar(const RooArgSet& allVars, const char* wgtName)
207{
208 if(wgtName) {
209 RooRealVar* wgt = dynamic_cast<RooRealVar*>(allVars.find(wgtName)) ;
210 return wgt ;
211 }
212 return nullptr ;
213}
214
215
216////////////////////////////////////////////////////////////////////////////////
217
218RooTreeDataStore::RooTreeDataStore(const RooTreeDataStore& other, const char* newname) :
219 RooAbsDataStore(other,newname),
220 _varsww(other._varsww),
221 _wgtVar(other._wgtVar),
222 _extWgtArray(other._extWgtArray),
223 _extWgtErrLoArray(other._extWgtErrLoArray),
224 _extWgtErrHiArray(other._extWgtErrHiArray),
225 _extSumW2Array(other._extSumW2Array),
226 _curWgt(other._curWgt),
227 _curWgtErrLo(other._curWgtErrLo),
228 _curWgtErrHi(other._curWgtErrHi),
229 _curWgtErr(other._curWgtErr)
230{
231 initialize() ;
232 loadValues(&other) ;
233}
234
235
236////////////////////////////////////////////////////////////////////////////////
237
238RooTreeDataStore::RooTreeDataStore(const RooTreeDataStore& other, const RooArgSet& vars, const char* newname) :
239 RooAbsDataStore(other,varsNoWeight(vars,other._wgtVar?other._wgtVar->GetName():nullptr),newname),
240 _varsww(vars),
241 _wgtVar(other._wgtVar?weightVar(vars,other._wgtVar->GetName()):nullptr),
242 _extWgtArray(other._extWgtArray),
243 _extWgtErrLoArray(other._extWgtErrLoArray),
244 _extWgtErrHiArray(other._extWgtErrHiArray),
245 _extSumW2Array(other._extSumW2Array),
246 _curWgt(other._curWgt),
247 _curWgtErrLo(other._curWgtErrLo),
248 _curWgtErrHi(other._curWgtErrHi),
249 _curWgtErr(other._curWgtErr)
250{
251 initialize() ;
252 loadValues(&other) ;
253}
254
255
256
257
258////////////////////////////////////////////////////////////////////////////////
259/// Destructor
260
262{
263 if (_tree) {
264 delete _tree ;
265 }
266}
267
268
269
270////////////////////////////////////////////////////////////////////////////////
271/// One-time initialization common to all constructor forms. Attach
272/// variables of internal ArgSet to the corresponding TTree branches
273
275{
276 // Recreate (empty) cache tree
278
279 // Attach each variable to the dataset
280 for (auto var : _varsww) {
281 var->attachToTree(*_tree,_defTreeBufSize) ;
282 }
283}
284
285
286
287
288
289////////////////////////////////////////////////////////////////////////////////
290/// Create TTree object that lives in memory, independent of current
291/// location of gDirectory
292
294{
295 if (!_tree) {
296 _tree = new TTree(name.c_str(),title.c_str());
299 _tree->SetDirectory(nullptr);
300 }
301
302 TString pwd(gDirectory->GetPath()) ;
303 TString memDir(gROOT->GetName()) ;
304 memDir.Append(":/") ;
305 bool notInMemNow= (pwd!=memDir) ;
306
307 // std::cout << "RooTreeData::createTree pwd=" << pwd << " memDir=" << memDir << " notInMemNow = " << (notInMemNow?"T":"F") << std::endl ;
308
309 if (notInMemNow) {
310 gDirectory->cd(memDir) ;
311 }
312
313 if (notInMemNow) {
314 gDirectory->cd(pwd) ;
315 }
316
317}
318
319
320
321
322////////////////////////////////////////////////////////////////////////////////
323/// Load values from tree 't' into this data collection, optionally
324/// selecting events using the RooFormulaVar 'select'.
325///
326/// The source tree 't' is cloned to not disturb its branch
327/// structure when retrieving information from it.
328void RooTreeDataStore::loadValues(const TTree *t, const RooFormulaVar* select, const char* /*rangeName*/, Int_t /*nStart*/, Int_t /*nStop*/)
329{
330 // Make our local copy of the tree, so we can safely loop through it.
331 // We need a custom deleter, because if we don't deregister the Tree from the directory
332 // of the original, it tears it down at destruction time!
333 auto deleter = [](TTree* tree){tree->SetDirectory(nullptr); delete tree;};
334 std::unique_ptr<TTree, decltype(deleter)> tClone(static_cast<TTree*>(t->Clone()), deleter);
335 tClone->SetDirectory(t->GetDirectory());
336
337 // Clone list of variables
338 RooArgSet sourceArgSet;
339 _varsww.snapshot(sourceArgSet, false);
340
341 // Check that we have the branches:
342 bool missingBranches = false;
343 for (const auto var : sourceArgSet) {
344 if (!tClone->GetBranch(var->GetName())) {
345 missingBranches = true;
346 coutE(InputArguments) << "Didn't find a branch in Tree '" << tClone->GetName() << "' to read variable '"
347 << var->GetName() << "' from."
348 << "\n\tNote: Name the RooFit variable the same as the branch." << std::endl;
349 }
350 }
351 if (missingBranches) {
352 coutE(InputArguments) << "Cannot import data from TTree '" << tClone->GetName()
353 << "' because some branches are missing !" << std::endl;
354 return;
355 }
356
357 // Attach args in cloned list to cloned source tree
358 for (const auto sourceArg : sourceArgSet) {
359 sourceArg->attachToTree(*tClone,_defTreeBufSize) ;
360 }
361
362 // Redirect formula servers to sourceArgSet
363 std::unique_ptr<RooFormulaVar> selectClone;
364 if (select) {
365 selectClone.reset( static_cast<RooFormulaVar*>(select->cloneTree()) );
366 selectClone->recursiveRedirectServers(sourceArgSet) ;
367 selectClone->setOperMode(RooAbsArg::ADirty,true) ;
368 }
369
370 // Loop over events in source tree
371 Int_t numInvalid(0) ;
372 const Long64_t nevent = tClone->GetEntries();
373 for(Long64_t i=0; i < nevent; ++i) {
374 const auto entryNumber = tClone->GetEntryNumber(i);
375 if (entryNumber<0) break;
376 tClone->GetEntry(entryNumber,1);
377
378 // Copy from source to destination
379 bool allOK(true) ;
380 for (unsigned int j=0; j < sourceArgSet.size(); ++j) {
381 auto destArg = _varsww[j];
382 const auto sourceArg = sourceArgSet[j];
383
384 destArg->copyCache(sourceArg) ;
385 sourceArg->copyCache(destArg) ;
386 if (!destArg->isValid()) {
387 numInvalid++ ;
388 allOK=false ;
389 if (numInvalid < 5) {
390 auto& log = coutI(DataHandling);
391 log << "RooTreeDataStore::loadValues(" << GetName() << ") Skipping event #" << i << " because " << destArg->GetName()
392 << " cannot accommodate the value ";
393 if(sourceArg->isCategory()) {
394 log << static_cast<RooAbsCategory*>(sourceArg)->getCurrentIndex();
395 } else {
396 log << static_cast<RooAbsReal*>(sourceArg)->getVal();
397 }
398 log << std::endl;
399 } else if (numInvalid == 5) {
400 coutI(DataHandling) << "RooTreeDataStore::loadValues(" << GetName() << ") Skipping ..." << std::endl;
401 }
402 break ;
403 }
404 }
405
406 // Does this event pass the cuts?
407 if (!allOK || (selectClone && selectClone->getVal()==0)) {
408 continue ;
409 }
410
411 fill() ;
412 }
413
414 if (numInvalid>0) {
415 coutW(DataHandling) << "RooTreeDataStore::loadValues(" << GetName() << ") Ignored " << numInvalid << " out-of-range events" << std::endl ;
416 }
417
418 SetTitle(t->GetTitle());
419}
420
421
422
423
424
425
426////////////////////////////////////////////////////////////////////////////////
427/// Load values from dataset 't' into this data collection, optionally
428/// selecting events using 'select' RooFormulaVar
429///
430
432 const char* rangeName, std::size_t nStart, std::size_t nStop)
433{
434 // Redirect formula servers to source data row
435 std::unique_ptr<RooFormulaVar> selectClone;
436 if (select) {
437 selectClone.reset( static_cast<RooFormulaVar*>(select->cloneTree()) );
438 selectClone->recursiveRedirectServers(*ads->get()) ;
439 selectClone->setOperMode(RooAbsArg::ADirty,true) ;
440 }
441
442 // Force RDS internal initialization
443 ads->get(0) ;
444
445 // Loop over events in source tree
446 const auto numEntr = static_cast<std::size_t>(ads->numEntries());
447 std::size_t nevent = nStop < numEntr ? nStop : numEntr;
448
449 auto TDS = dynamic_cast<const RooTreeDataStore*>(ads) ;
450 if (TDS) {
451 const_cast<RooTreeDataStore*>(TDS)->resetBuffers();
452 }
453
454 std::vector<std::string> ranges;
455 if (rangeName) {
456 ranges = ROOT::Split(rangeName, ",");
457 }
458
459 for (auto i=nStart; i < nevent ; ++i) {
460 ads->get(i) ;
461
462 // Does this event pass the cuts?
463 if (selectClone && selectClone->getVal()==0) {
464 continue ;
465 }
466
467
468 if (TDS) {
469 _varsww.assignValueOnly(TDS->_varsww) ;
470 } else {
471 _varsww.assignValueOnly(*ads->get()) ;
472 }
473
474 // Check that all copied values are valid
475 bool allValid = true;
476 for (const auto arg : _varsww) {
477 allValid = arg->isValid() && (ranges.empty() || std::any_of(ranges.begin(), ranges.end(),
478 [arg](const std::string& range){return arg->inRange(range.c_str());}) );
479 if (!allValid)
480 break ;
481 }
482
483 if (!allValid) {
484 continue ;
485 }
486
487 fill() ;
488 }
489
490 if (TDS) {
491 const_cast<RooTreeDataStore*>(TDS)->restoreAlternateBuffers();
492 }
493
494 SetTitle(ads->GetTitle());
495}
496
497
498////////////////////////////////////////////////////////////////////////////////
499/// Interface function to TTree::Fill
500
502{
503 return _tree->Fill() ;
504}
505
506
507
508////////////////////////////////////////////////////////////////////////////////
509/// Load the n-th data point (n='index') in memory
510/// and return a pointer to the internal RooArgSet
511/// holding its coordinates.
512
514{
515 checkInit() ;
516
517 Int_t ret = _tree->GetEntry(index, 1);
518
519 if(!ret) return nullptr;
520
521 if (_doDirtyProp) {
522 // Raise all dirty flags
523 for (auto var : _vars) {
524 var->setValueDirty(); // This triggers recalculation of all clients
525 }
526 }
527
528 // Update current weight cache
529 if (_extWgtArray) {
530
531 // If external array is specified use that
536
537 } else if (_wgtVar) {
538
539 // Otherwise look for weight variable
540 _curWgt = _wgtVar->getVal() ;
544
545 } else {
546
547 // Otherwise return 1
548 _curWgt=1.0 ;
549 _curWgtErrLo = 0 ;
550 _curWgtErrHi = 0 ;
551 _curWgtErr = 0 ;
552
553 }
554
555 return &_vars;
556}
557
558
559////////////////////////////////////////////////////////////////////////////////
560/// Return the weight of the n-th data point (n='index') in memory
561
563{
564 return _curWgt ;
565}
566
567
568////////////////////////////////////////////////////////////////////////////////
569
571{
572 if (_extWgtArray) {
573
574 // We have a weight array, use that info
575
576 // Return symmetric error on current bin calculated either from Poisson statistics or from SumOfWeights
577 double lo = 0;
578 double hi = 0;
579 weightError(lo,hi,etype) ;
580 return (lo+hi)/2 ;
581
582 } else if (_wgtVar) {
583
584 // We have a weight variable, use that info
585 if (_wgtVar->hasAsymError()) {
586 return ( _wgtVar->getAsymErrorHi() - _wgtVar->getAsymErrorLo() ) / 2 ;
587 } else {
588 return _wgtVar->getError() ;
589 }
590
591 }
592
593 // We have no weights
594 return 0.0;
595}
596
597
598
599////////////////////////////////////////////////////////////////////////////////
600
601void RooTreeDataStore::weightError(double& lo, double& hi, RooAbsData::ErrorType etype) const
602{
603 if (_extWgtArray) {
604
605 // We have a weight array, use that info
606 switch (etype) {
607
608 case RooAbsData::Auto:
609 throw string(Form("RooDataHist::weightError(%s) error type Auto not allowed here",GetName())) ;
610 break ;
611
613 throw string(Form("RooDataHist::weightError(%s) error type Expected not allowed here",GetName())) ;
614 break ;
615
617 // Weight may be preset or precalculated
618 if (_curWgtErrLo>=0) {
619 lo = _curWgtErrLo ;
620 hi = _curWgtErrHi ;
621 return ;
622 }
623
624 // Otherwise Calculate poisson errors
625 double ym;
626 double yp;
628 lo = weight()-ym ;
629 hi = yp-weight() ;
630 return ;
631
633 lo = _curWgtErr ;
634 hi = _curWgtErr ;
635 return ;
636
637 case RooAbsData::None:
638 lo = 0 ;
639 hi = 0 ;
640 return ;
641 }
642
643 } else if (_wgtVar) {
644
645 // We have a weight variable, use that info
646 if (_wgtVar->hasAsymError()) {
648 lo = _wgtVar->getAsymErrorLo() ;
649 } else {
650 hi = _wgtVar->getError() ;
651 lo = _wgtVar->getError() ;
652 }
653
654 } else {
655
656 // We are unweighted
657 lo=0 ;
658 hi=0 ;
659
660 }
661}
662
663
664////////////////////////////////////////////////////////////////////////////////
665/// Change name of internal observable named 'from' into 'to'
666
667bool RooTreeDataStore::changeObservableName(const char* from, const char* to)
668{
669 // Find observable to be changed
670 RooAbsArg* var = _vars.find(from) ;
671
672 // Check that we found it
673 if (!var) {
674 coutE(InputArguments) << "RooTreeDataStore::changeObservableName(" << GetName() << " no observable " << from << " in this dataset" << std::endl ;
675 return true ;
676 }
677
678 // Process name change
679 TString oldBranchName = var->cleanBranchName() ;
680 var->SetName(to) ;
681
682 // Change the branch name as well
683 if (_tree->GetBranch(oldBranchName.Data())) {
684
685 // Simple case varName = branchName
686 _tree->GetBranch(oldBranchName.Data())->SetName(var->cleanBranchName().Data()) ;
687
688 // Process any error branch if existing
689 if (_tree->GetBranch(Form("%s_err",oldBranchName.Data()))) {
690 _tree->GetBranch(Form("%s_err",oldBranchName.Data()))->SetName(Form("%s_err",var->cleanBranchName().Data())) ;
691 }
692 if (_tree->GetBranch(Form("%s_aerr_lo",oldBranchName.Data()))) {
693 _tree->GetBranch(Form("%s_aerr_lo",oldBranchName.Data()))->SetName(Form("%s_aerr_lo",var->cleanBranchName().Data())) ;
694 }
695 if (_tree->GetBranch(Form("%s_aerr_hi",oldBranchName.Data()))) {
696 _tree->GetBranch(Form("%s_aerr_hi",oldBranchName.Data()))->SetName(Form("%s_aerr_hi",var->cleanBranchName().Data())) ;
697 }
698
699 } else {
700
701 // Native category case branchNames = varName_idx and varName_lbl
702 if (_tree->GetBranch(Form("%s_idx",oldBranchName.Data()))) {
703 _tree->GetBranch(Form("%s_idx",oldBranchName.Data()))->SetName(Form("%s_idx",var->cleanBranchName().Data())) ;
704 }
705 if (_tree->GetBranch(Form("%s_lbl",oldBranchName.Data()))) {
706 _tree->GetBranch(Form("%s_lbl",oldBranchName.Data()))->SetName(Form("%s_lb",var->cleanBranchName().Data())) ;
707 }
708
709 }
710
711 return false ;
712}
713
714
715
716////////////////////////////////////////////////////////////////////////////////
717/// Add a new column to the data set which holds the pre-calculated values
718/// of 'newVar'. This operation is only meaningful if 'newVar' is a derived
719/// value.
720///
721/// The return value points to the added element holding 'newVar's value
722/// in the data collection. The element is always the corresponding fundamental
723/// type of 'newVar' (e.g. a RooRealVar if 'newVar' is a RooFormulaVar)
724///
725/// Note: This function is explicitly NOT intended as a speed optimization
726/// opportunity for the user. Components of complex PDFs that can be
727/// precalculated with the dataset are automatically identified as such
728/// and will be precalculated when fitting to a dataset
729///
730/// By forcibly precalculating functions with non-trivial Jacobians,
731/// or functions of multiple variables occurring in the data set,
732/// using addColumn(), you may alter the outcome of the fit.
733///
734/// Only in cases where such a modification of fit behaviour is intentional,
735/// this function should be used.
736
738{
739 checkInit() ;
740
741 // Create a fundamental object of the right type to hold newVar values
742 auto valHolder = std::unique_ptr<RooAbsArg>{newVar.createFundamental()}.release();
743 // Sanity check that the holder really is fundamental
744 if(!valHolder->isFundamental()) {
745 coutE(InputArguments) << GetName() << "::addColumn: holder argument is not fundamental: \""
746 << valHolder->GetName() << "\"" << std::endl;
747 return nullptr;
748 }
749
750 // WVE need to reset TTRee buffers to original datamembers here
751 resetBuffers() ;
752
753 // Clone variable and attach to cloned tree
754 std::unique_ptr<RooAbsArg> newVarClone{newVar.cloneTree()};
755 newVarClone->recursiveRedirectServers(_vars,false) ;
756
757 // Attach value place holder to this tree
758 ((RooAbsArg*)valHolder)->attachToTree(*_tree,_defTreeBufSize) ;
759 _vars.add(*valHolder) ;
760 _varsww.add(*valHolder) ;
761
762
763 // Fill values of placeholder
764 for (int i=0 ; i < _tree->GetEntries() ; i++) {
765 get(i) ;
766
767 newVarClone->syncCache(&_vars) ;
768 valHolder->copyCache(newVarClone.get());
769 valHolder->fillTreeBranch(*_tree) ;
770 }
771
772 // WVE need to restore TTRee buffers to previous values here
774
775 if (adjustRange) {
776// // Set range of valHolder to (just) bracket all values stored in the dataset
777// double vlo,vhi ;
778// RooRealVar* rrvVal = dynamic_cast<RooRealVar*>(valHolder) ;
779// if (rrvVal) {
780// getRange(*rrvVal,vlo,vhi,0.05) ;
781// rrvVal->setRange(vlo,vhi) ;
782// }
783 }
784
785 return valHolder ;
786}
787
788
789////////////////////////////////////////////////////////////////////////////////
790/// Merge columns of supplied data set(s) with this data set. All
791/// data sets must have equal number of entries. In case of
792/// duplicate columns the column of the last dataset in the list
793/// prevails
794
795RooAbsDataStore* RooTreeDataStore::merge(const RooArgSet& allVars, list<RooAbsDataStore*> dstoreList)
796{
797 RooTreeDataStore* mergedStore = new RooTreeDataStore("merged","merged",allVars) ;
798
799 Int_t nevt = dstoreList.front()->numEntries() ;
800 for (int i=0 ; i<nevt ; i++) {
801
802 // Cope data from self
803 mergedStore->_vars.assign(*get(i)) ;
804
805 // Copy variables from merge sets
806 for (list<RooAbsDataStore*>::iterator iter = dstoreList.begin() ; iter!=dstoreList.end() ; ++iter) {
807 const RooArgSet* partSet = (*iter)->get(i) ;
808 mergedStore->_vars.assign(*partSet) ;
809 }
810
811 mergedStore->fill() ;
812 }
813 return mergedStore ;
814}
815
816
817
818
819
820////////////////////////////////////////////////////////////////////////////////
821
823{
824 Int_t nevt = other.numEntries() ;
825 for (int i=0 ; i<nevt ; i++) {
826 _vars.assign(*other.get(i)) ;
827 if (_wgtVar) {
828 _wgtVar->setVal(other.weight()) ;
829 }
830
831 fill() ;
832 }
833}
834
835
836////////////////////////////////////////////////////////////////////////////////
837
839{
840 if (_wgtVar) {
841
842 double sum(0);
843 double carry(0);
844 Int_t nevt = numEntries() ;
845 for (int i=0 ; i<nevt ; i++) {
846 get(i) ;
847 // Kahan's algorithm for summing to avoid loss of precision
848 double y = _wgtVar->getVal() - carry;
849 double t = sum + y;
850 carry = (t - sum) - y;
851 sum = t;
852 }
853 return sum ;
854
855 } else if (_extWgtArray) {
856
857 double sum(0);
858 double carry(0);
859 Int_t nevt = numEntries() ;
860 for (int i=0 ; i<nevt ; i++) {
861 // Kahan's algorithm for summing to avoid loss of precision
862 double y = _extWgtArray[i] - carry;
863 double t = sum + y;
864 carry = (t - sum) - y;
865 sum = t;
866 }
867 return sum ;
868
869 } else {
870
871 return numEntries() ;
872
873 }
874}
875
876
877
878
879////////////////////////////////////////////////////////////////////////////////
880
882{
883 return _tree->GetEntries() ;
884}
885
886
887
888////////////////////////////////////////////////////////////////////////////////
889
891{
892 _tree->Reset() ;
893}
894
895
896
897////////////////////////////////////////////////////////////////////////////////
898
900{
902 for (const auto arg : _varsww) {
903 RooAbsArg* extArg = extObs.find(arg->GetName()) ;
904 if (extArg) {
905 if (arg->getAttribute("StoreError")) {
906 extArg->setAttribute("StoreError") ;
907 }
908 if (arg->getAttribute("StoreAsymError")) {
909 extArg->setAttribute("StoreAsymError") ;
910 }
911 extArg->attachToTree(*_tree) ;
912 _attachedBuffers.add(*extArg) ;
913 }
914 }
915}
916
917
918
919////////////////////////////////////////////////////////////////////////////////
920
922{
923 for(RooAbsArg * arg : _varsww) {
924 arg->attachToTree(*_tree) ;
925 }
926}
927
928
929
930////////////////////////////////////////////////////////////////////////////////
931
933{
934 for(RooAbsArg * arg : _attachedBuffers) {
935 arg->attachToTree(*_tree) ;
936 }
937}
938
939
940
941////////////////////////////////////////////////////////////////////////////////
942
944{
945 if (_defCtor) {
946 const_cast<RooTreeDataStore*>(this)->initialize() ;
947 _defCtor = false ;
948 }
949}
950
951////////////////////////////////////////////////////////////////////////////////
952/// Stream an object of class RooTreeDataStore.
953
955{
956 if (R__b.IsReading()) {
957 UInt_t R__s;
958 UInt_t R__c;
959 const Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
960
961 R__b.ReadClassBuffer(RooTreeDataStore::Class(), this, R__v, R__s, R__c);
962
963 if (!_tree) {
964 // If the tree has not been deserialised automatically, it is time to load
965 // it now.
966 TFile* parent = dynamic_cast<TFile*>(R__b.GetParent());
967 assert(parent);
968 parent->GetObject(makeTreeName().c_str(), _tree);
969 }
970
971 initialize();
972
973 } else {
974
975 TTree* tmpTree = _tree;
976 auto parent = dynamic_cast<TDirectory*>(R__b.GetParent());
977 if (_tree && parent) {
978 // Large trees cannot be written because of the 1Gb I/O limitation.
979 // Here, we take the tree away from our instance, write it, and continue
980 // to write the rest of the class normally
981 auto tmpDir = _tree->GetDirectory();
982
983 _tree->SetDirectory(parent);
984 _tree->FlushBaskets(false);
985 parent->WriteObject(_tree, makeTreeName().c_str());
986 _tree->SetDirectory(tmpDir);
987 _tree = nullptr;
988 }
989
991
992 _tree = tmpTree;
993 }
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// Generate a name for the storage tree from the name and title of this instance.
999 std::string title = GetTitle();
1000 std::replace(title.begin(), title.end(), ' ', '_');
1001 std::replace(title.begin(), title.end(), '-', '_');
1002 return std::string("RooTreeDataStore_") + GetName() + "_" + title;
1003}
1004
1005
1006////////////////////////////////////////////////////////////////////////////////
1007/// Get the weights of the events in the range [first, first+len).
1008/// This implementation will fill a vector with every event retrieved one by one
1009/// (even if the weight is constant). Then, it returns a span.
1010std::span<const double> RooTreeDataStore::getWeightBatch(std::size_t first, std::size_t len) const {
1011
1012 if (_extWgtArray) {
1013 return {_extWgtArray + first, len};
1014 }
1015
1016 if (!_weightBuffer) {
1017 _weightBuffer = std::make_unique<std::vector<double>>();
1018 _weightBuffer->reserve(len);
1019
1020 for (int i = 0; i < _tree->GetEntries(); ++i) {
1021 _weightBuffer->push_back(weight(i));
1022 }
1023 }
1024
1025 return {_weightBuffer->data() + first, len};
1026}
#define coutI(a)
#define coutW(a)
#define coutE(a)
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
#define gDirectory
Definition TDirectory.h:385
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:142
#define hi
#define gROOT
Definition TROOT.h:417
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2571
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
bool recursiveRedirectServers(const RooAbsCollection &newSet, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
void SetName(const char *name) override
Set the name of the TNamed.
virtual RooFit::OwningPtr< RooAbsArg > createFundamental(const char *newname=nullptr) const =0
Create a fundamental-type object that stores our type of value.
virtual void attachToTree(TTree &t, Int_t bufSize=32000)=0
Overloadable function for derived classes to implement attachment as branch to a TTree.
virtual RooAbsArg * cloneTree(const char *newname=nullptr) const
Clone tree expression of objects.
TString cleanBranchName() const
Construct a mangled name from the actual name that is free of any math symbols that might be interpre...
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
bool contains(const char *name) const
Check if collection contains an argument with a specific name.
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
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.
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...
Storage_t::size_type size() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for a data collection.
virtual const RooArgSet * get(Int_t index) const =0
bool _doDirtyProp
Switch do (de)activate dirty state propagation when loading a data point.
virtual double weight() const =0
virtual Int_t numEntries() const =0
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
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.
bool getPoissonInterval(Int_t n, double &mu1, double &mu2, double nSigma=1) const
Calculate a confidence interval for the expected number of events given n observed (unweighted) event...
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:59
bool hasAsymError(bool allowZero=true) const
Definition RooRealVar.h:65
double getAsymErrorHi() const
Definition RooRealVar.h:64
double getAsymErrorLo() const
Definition RooRealVar.h:63
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
Weight of current event.
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
void attachBuffers(const RooArgSet &extObs) override
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
! Was object constructed with default ctor?
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 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
! Buffer for weights in case a batch of values is requested.
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'.
virtual const RooArgSet * get() const
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition TBuffer.cxx:261
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
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:213
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:73
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
Basic string class.
Definition TString.h:137
const char * Data() const
Definition TString.h:385
TString & Append(const char *cs)
Definition TString.h:582
A TTree represents a columnar dataset.
Definition TTree.h:95
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4676
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5459
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:5207
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:5747
TDirectory * GetDirectory() const
Definition TTree.h:523
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:9380
virtual Long64_t GetEntries() const
Definition TTree.h:524
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8341
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:2335