Logo ROOT  
Reference Guide
RooDataSet.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 RooDataSet.cxx
19\class RooDataSet
20\ingroup Roofitcore
21
22RooDataSet is a container class to hold unbinned data. The binned equivalent is
23RooDataHist. In RooDataSet, each data point in N-dimensional space is represented
24by a RooArgSet of RooRealVar, RooCategory or RooStringVar objects, which can be
25retrieved using get().
26
27Since RooDataSet saves every event, it allows for fits with highest precision. With a large
28amount of data, however, it could be beneficial to represent them in binned form,
29i.e., RooDataHist. Binning the data will incur a loss of information, though.
30RooDataHist on the other hand may suffer from the curse of dimensionality if a high-dimensional
31problem with a lot of bins on each axis is tackled.
32
33### Inspecting a dataset
34Inspect a dataset using Print() with the "verbose" option:
35```
36dataset->Print("V");
37dataset->get(0)->Print("V");
38dataset->get(1)->Print("V");
39...
40```
41
42### Plotting data.
43See RooAbsData::plotOn().
44
45
46### Storage strategy
47There are two storage backends:
48- RooVectorDataStore (default): std::vectors in memory. They are fast, but they
49cannot be serialised if the dataset exceeds a size of 1 Gb
50- RooTreeDataStore: Uses a TTree, which can be file backed if a file is opened
51before creating the dataset. This significantly reduces the memory pressure, as the
52baskets of the tree can be written to a file, and only the basket that's currently
53being read stays in RAM.
54 - Enable tree-backed storage similar to this:
55 ```
56 TFile outputFile("filename.root", "RECREATE");
57 RooAbsData::setDefaultStorageType(RooAbsData::Tree);
58 RooDataSet mydata(...);
59 ```
60 - Or convert an existing memory-backed data storage:
61 ```
62 RooDataSet mydata(...);
63
64 TFile outputFile("filename.root", "RECREATE");
65 mydata.convertToTreeStore();
66 ```
67
68For the inverse conversion, see `RooAbsData::convertToVectorStore()`.
69
70
71### Creating a dataset using RDataFrame
72\see RooAbsDataHelper, rf408_RDataFrameToRooFit.C
73
74### Uniquely identifying RooDataSet objects
75
76\warning Before v6.28, it was ensured that no RooDataSet objects on the heap
77were located at an address that had already been used for a RooDataSet before.
78With v6.28, this is not guaranteed anymore. Hence, if your code uses pointer
79comparisons to uniquely identify RooDataSet instances, please consider using
80the new `RooAbsData::uniqueId()`.
81
82
83**/
84
85#include "RooDataSet.h"
86
87#include "RooPlot.h"
88#include "RooAbsReal.h"
89#include "Roo1DTable.h"
90#include "RooCategory.h"
91#include "RooFormulaVar.h"
92#include "RooArgList.h"
93#include "RooRealVar.h"
94#include "RooDataHist.h"
95#include "RooMsgService.h"
96#include "RooCmdConfig.h"
97#include "RooHist.h"
98#include "RooTreeDataStore.h"
99#include "RooVectorDataStore.h"
101#include "RooSentinel.h"
102#include "RooTrace.h"
103#include "RooHelpers.h"
104
105#include "ROOT/StringUtils.hxx"
106
107#include "Math/Util.h"
108#include "TTree.h"
109#include "TFile.h"
110#include "TBuffer.h"
111#include "strlcpy.h"
112#include "snprintf.h"
113
114#include <iostream>
115#include <memory>
116#include <fstream>
117
118
119using namespace std;
120
122
123#ifndef USEMEMPOOLFORDATASET
125#else
126
127#include "MemPoolForRooSets.h"
128
129RooDataSet::MemPool* RooDataSet::memPool() {
131 static auto * memPool = new RooDataSet::MemPool();
132 return memPool;
133}
134
135void RooDataSet::cleanup() {
136 auto pool = memPool();
137 pool->teardown();
138
139 //The pool will have to leak if it's not empty at this point.
140 if (pool->empty())
141 delete pool;
142}
143
144
145////////////////////////////////////////////////////////////////////////////////
146/// Overloaded new operator guarantees that all RooDataSets allocated with new
147/// have a unique address, a property that is exploited in several places
148/// in roofit to quickly index contents on normalization set pointers.
149/// The memory pool only allocates space for the class itself. The elements
150/// stored in the set are stored outside the pool.
151
152void* RooDataSet::operator new (size_t bytes)
153{
154 //This will fail if a derived class uses this operator
155 assert(sizeof(RooDataSet) == bytes);
156
157 return memPool()->allocate(bytes);
158}
159
160
161
162////////////////////////////////////////////////////////////////////////////////
163/// Memory is owned by pool, we need to do nothing to release it
164
165void RooDataSet::operator delete (void* ptr)
166{
167 // Decrease use count in pool that ptr is on
168 if (memPool()->deallocate(ptr))
169 return;
170
171 std::cerr << __func__ << " " << ptr << " is not in any of the pools." << std::endl;
172
173 // Not part of any pool; use global op delete:
174 ::operator delete(ptr);
175}
176
177#endif
178
179
180////////////////////////////////////////////////////////////////////////////////
181/// Default constructor for persistence
182
184{
186}
187
188namespace {
189
190struct FinalizeVarsOutput {
191 RooArgSet finalVars;
192 std::unique_ptr<RooRealVar> weight;
193 std::string weightVarName;
194 RooArgSet errorSet;
195};
196
197FinalizeVarsOutput finalizeVars(RooArgSet const &vars,
198 RooAbsArg * indexCat,
199 const char* wgtVarName,
200 RooAbsData* impData,
201 RooLinkedList const &impSliceData,
202 RooArgSet * errorSet)
203{
204 FinalizeVarsOutput out;
205 out.finalVars.add(vars);
206
207 // Gather all imported weighted datasets to infer the weight variable name
208 // and whether we need weight errors
209 std::vector<RooAbsData*> weightedImpDatas;
210 if(impData && impData->isWeighted()) weightedImpDatas.push_back(impData);
211 for(auto * data : static_range_cast<RooAbsData*>(impSliceData)) {
212 if(data->isWeighted()) {
213 weightedImpDatas.push_back(data);
214 }
215 }
216
217 bool needsWeightErrors = false;
218
219 // Figure out if the weight needs to store errors
220 for(RooAbsData * data : weightedImpDatas) {
221 if(dynamic_cast<RooDataHist const*>(data)) {
222 needsWeightErrors = true;
223 }
224 }
225
226 if (indexCat) {
227 out.finalVars.add(*indexCat, true);
228 }
229
230 out.weightVarName = wgtVarName ? wgtVarName : "";
231
232 if(out.weightVarName.empty()) {
233 // Even if no weight variable is specified, we want to have one if we are
234 // importing weighted datasets
235 for(RooAbsData * data : weightedImpDatas) {
236 if(auto ds = dynamic_cast<RooDataSet const*>(data)) {
237 // If the imported data is a RooDataSet, we take over its weight variable name
238 out.weightVarName = ds->weightVar()->GetName();
239 break;
240 } else {
241 out.weightVarName = RooFit::WeightVar().getString(0); // to get the default weight variable name
242 // Don't break here! The next imported data might be a RooDataSet,
243 // and in that case we want to take over its weight name instead of
244 // using the default one.
245 }
246 }
247 }
248
249 // If the weight variable is required but is not in the set, create and add
250 // it on the fly
251 RooAbsArg * wgtVar = out.finalVars.find(out.weightVarName.c_str());
252 if (!out.weightVarName.empty() && !wgtVar) {
253 const char* name = out.weightVarName.c_str();
254 out.weight = std::make_unique<RooRealVar>(name, name, 1.0);
255 wgtVar = out.weight.get();
256 out.finalVars.add(*out.weight);
257 }
258
259 if(needsWeightErrors) {
260 out.errorSet.add(*wgtVar);
261 }
262
263 // Combine the error set figured out by finalizeVars and the ones passed by the user
264 if(errorSet) out.errorSet.add(*errorSet, /*silent=*/true);
265
266 return out;
267}
268
269// generating an unbinned dataset from a binned one
270std::unique_ptr<RooDataSet> makeDataSetFromDataHist(RooDataHist const &hist)
271{
272 using namespace RooFit;
273
274 RooCmdArg const& wgtVarCmdArg = RooFit::WeightVar();
275 const char* wgtName = wgtVarCmdArg.getString(0);
276 // Instantiate weight variable here such that we can pass it to StoreError()
277 RooRealVar wgtVar{wgtName, wgtName, 1.0};
278
279 RooArgSet vars{*hist.get(), wgtVar};
280
281 // We have to explicitly store the errors that are implied by the sum of weights squared.
282 auto data = std::make_unique<RooDataSet>(hist.GetName(), hist.GetTitle(), vars, wgtVarCmdArg, StoreError(wgtVar));
283 for (int i = 0; i < hist.numEntries(); ++i) {
284 data->add(*hist.get(i), hist.weight(i), std::sqrt(hist.weightSquared(i)));
285 }
286
287 return data;
288}
289
290} // namespace
291
292////////////////////////////////////////////////////////////////////////////////
293/// Construct an unbinned dataset from a RooArgSet defining the dimensions of the data space. Optionally, data
294/// can be imported at the time of construction.
295///
296/// <table>
297/// <tr><th> %RooCmdArg <th> Effect
298/// <tr><td> Import(TTree*) <td> Import contents of given TTree. Only braches of the TTree that have names
299/// corresponding to those of the RooAbsArgs that define the RooDataSet are
300/// imported.
301/// <tr><td> ImportFromFile(const char* fileName, const char* treeName) <td> Import tree with given name from file with given name.
302/// <tr><td> Import(RooAbsData&)
303/// <td> Import contents of given RooDataSet or RooDataHist. Only observables that are common with the definition of this dataset will be imported
304/// <tr><td> Index(RooCategory&) <td> Prepare import of datasets into a N+1 dimensional RooDataSet
305/// where the extra discrete dimension labels the source of the imported histogram.
306/// <tr><td> Import(const char*, RooAbsData&)
307/// <td> Import a RooDataSet or RooDataHist to be associated with the given state name of the index category
308/// specified in Index(). If the given state name is not yet defined in the index
309/// category it will be added on the fly. The import command can be specified multiple times.
310/// <tr><td> Link(const char*, RooDataSet&) <td> Link contents of supplied RooDataSet to this dataset for given index category state name.
311/// In this mode, no data is copied and the linked dataset must be remain live for the duration
312/// of this dataset. Note that link is active for both reading and writing, so modifications
313/// to the aggregate dataset will also modify its components. Link() and Import() are mutually exclusive.
314/// <tr><td> OwnLinked() <td> Take ownership of all linked datasets
315/// <tr><td> Import(std::map<string,RooAbsData*>&) <td> As above, but allows specification of many imports in a single operation
316/// <tr><td> Link(std::map<string,RooDataSet*>&) <td> As above, but allows specification of many links in a single operation
317/// <tr><td> Cut(const char*) <br>
318/// Cut(RooFormulaVar&)
319/// <td> Apply the given cut specification when importing data
320/// <tr><td> CutRange(const char*) <td> Only accept events in the observable range with the given name
321/// <tr><td> WeightVar(const char*) <br>
322/// WeightVar(const RooAbsArg&)
323/// <td> Interpret the given variable as event weight rather than as observable
324/// <tr><td> StoreError(const RooArgSet&) <td> Store symmetric error along with value for given subset of observables
325/// <tr><td> StoreAsymError(const RooArgSet&) <td> Store asymmetric error along with value for given subset of observables
326/// <tr><td> `GlobalObservables(const RooArgSet&)` <td> Define the set of global observables to be stored in this RooDataSet.
327/// A snapshot of the passed RooArgSet is stored, meaning the values wont't change unexpectedly.
328/// </table>
329///
330
331RooDataSet::RooDataSet(RooStringView name, RooStringView title, const RooArgSet& vars, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
332 const RooCmdArg& arg4,const RooCmdArg& arg5,const RooCmdArg& arg6,const RooCmdArg& arg7,const RooCmdArg& arg8) :
333 RooAbsData(name,title,{})
334{
336
337 // Define configuration for this method
338 RooCmdConfig pc(Form("RooDataSet::ctor(%s)",GetName())) ;
339 pc.defineInt("ownLinked","OwnLinked",0) ;
340 pc.defineObject("impTree","ImportTree",0) ;
341 pc.defineObject("impData","ImportData",0) ;
342 pc.defineObject("indexCat","IndexCat",0) ;
343 pc.defineObject("impSliceData","ImportDataSlice",0,0,true) ; // array
344 pc.defineString("impSliceState","ImportDataSlice",0,"",true) ; // array
345 pc.defineObject("lnkSliceData","LinkDataSlice",0,0,true) ; // array
346 pc.defineString("lnkSliceState","LinkDataSlice",0,"",true) ; // array
347 pc.defineString("cutSpec","CutSpec",0,"") ;
348 pc.defineObject("cutVar","CutVar",0) ;
349 pc.defineString("cutRange","CutRange",0,"") ;
350 pc.defineString("wgtVarName","WeightVarName",0,"") ;
351 pc.defineInt("newWeight1","WeightVarName",0,0) ;
352 pc.defineString("fname","ImportFromFile",0,"") ;
353 pc.defineString("tname","ImportFromFile",1,"") ;
354 pc.defineObject("wgtVar","WeightVar",0) ;
355 pc.defineInt("newWeight2","WeightVar",0,0) ;
356 pc.defineObject("dummy1","ImportDataSliceMany",0) ;
357 pc.defineObject("dummy2","LinkDataSliceMany",0) ;
358 pc.defineSet("errorSet","StoreError",0) ;
359 pc.defineSet("asymErrSet","StoreAsymError",0) ;
360 pc.defineSet("glObs","GlobalObservables",0,0) ;
361 pc.defineMutex("ImportTree","ImportData","ImportDataSlice","LinkDataSlice","ImportFromFile") ;
362 pc.defineMutex("CutSpec","CutVar") ;
363 pc.defineMutex("WeightVarName","WeightVar") ;
364 pc.defineDependency("ImportDataSlice","IndexCat") ;
365 pc.defineDependency("LinkDataSlice","IndexCat") ;
366 pc.defineDependency("OwnLinked","LinkDataSlice") ;
367
368
370 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
371 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
372 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
373 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
374
375 // Process & check varargs
376 pc.process(l) ;
377 if (!pc.ok(true)) {
378 const std::string errMsg = "Error in RooDataSet constructor: command argument list could not be processed";
379 coutE(InputArguments) << errMsg << std::endl;
380 throw std::invalid_argument(errMsg);
381 }
382
383 if(pc.getSet("glObs")) setGlobalObservables(*pc.getSet("glObs"));
384
385 // Extract relevant objects
386 TTree* impTree = static_cast<TTree*>(pc.getObject("impTree")) ;
387 auto impData = static_cast<RooAbsData*>(pc.getObject("impData")) ;
388 RooFormulaVar* cutVar = static_cast<RooFormulaVar*>(pc.getObject("cutVar")) ;
389 const char* cutSpec = pc.getString("cutSpec","",true) ;
390 const char* cutRange = pc.getString("cutRange","",true) ;
391 const char* wgtVarName = pc.getString("wgtVarName","",true) ;
392 RooRealVar* wgtVar = static_cast<RooRealVar*>(pc.getObject("wgtVar")) ;
393 const char* impSliceNames = pc.getString("impSliceState","",true) ;
394 const RooLinkedList& impSliceData = pc.getObjectList("impSliceData") ;
395 const char* lnkSliceNames = pc.getString("lnkSliceState","",true) ;
396 const RooLinkedList& lnkSliceData = pc.getObjectList("lnkSliceData") ;
397 RooCategory* indexCat = static_cast<RooCategory*>(pc.getObject("indexCat")) ;
398 RooArgSet* asymErrorSet = pc.getSet("asymErrSet") ;
399 const char* fname = pc.getString("fname") ;
400 const char* tname = pc.getString("tname") ;
401 Int_t ownLinked = pc.getInt("ownLinked") ;
402 Int_t newWeight = pc.getInt("newWeight1") + pc.getInt("newWeight2") ;
403
404 // Lookup name of weight variable if it was specified by object reference
405 if(wgtVar) {
406 wgtVarName = wgtVar->GetName();
407 }
408
409 auto finalVarsInfo = finalizeVars(vars,indexCat,wgtVarName,impData,impSliceData, pc.getSet("errorSet"));
410 initializeVars(finalVarsInfo.finalVars);
411 if(!finalVarsInfo.weightVarName.empty()) {
412 wgtVarName = finalVarsInfo.weightVarName.c_str();
413 }
414
415 RooArgSet* errorSet = finalVarsInfo.errorSet.empty() ? nullptr : &finalVarsInfo.errorSet;
416
417 // Case 1 --- Link multiple dataset as slices
418 if (lnkSliceNames) {
419
420 // Make import mapping if index category is specified
421 map<string,RooAbsData*> hmap ;
422 if (indexCat) {
423 char tmp[64000];
424 strlcpy(tmp, lnkSliceNames, 64000);
425 char *token = strtok(tmp, ",");
426 auto hiter = lnkSliceData.begin();
427 while (token) {
428 hmap[token] = static_cast<RooAbsData *>(*hiter);
429 token = strtok(0, ",");
430 ++hiter;
431 }
432 }
433
434 appendToDir(this,true) ;
435
436 // Initialize RooDataSet with optional weight variable
437 initialize(0) ;
438
439 map<string,RooAbsDataStore*> storeMap ;
440 RooCategory* icat = (RooCategory*) (indexCat ? _vars.find(indexCat->GetName()) : 0 ) ;
441 if (!icat) {
442 throw std::string("RooDataSet::RooDataSet() ERROR in constructor, cannot find index category") ;
443 }
444 for (map<string,RooAbsData*>::iterator hiter = hmap.begin() ; hiter!=hmap.end() ; ++hiter) {
445 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
446 if (indexCat && !indexCat->hasLabel(hiter->first)) {
447 indexCat->defineType(hiter->first) ;
448 coutI(InputArguments) << "RooDataSet::ctor(" << GetName() << ") defining state \"" << hiter->first << "\" in index category " << indexCat->GetName() << endl ;
449 }
450 if (icat && !icat->hasLabel(hiter->first)) {
451 icat->defineType(hiter->first) ;
452 }
453 icat->setLabel(hiter->first.c_str()) ;
454 storeMap[icat->getCurrentLabel()]=hiter->second->store() ;
455
456 // Take ownership of slice if requested
457 if (ownLinked) {
458 addOwnedComponent(hiter->first.c_str(),*hiter->second) ;
459 }
460 }
461
462 // Create composite datastore
463 _dstore = std::make_unique<RooCompositeDataStore>(name,title,_vars,*icat,storeMap) ;
464
465 return;
466 }
467
468 // Create empty datastore
469 RooTreeDataStore* tstore = nullptr;
470 if (defaultStorageType==Tree) {
471 _dstore = std::make_unique<RooTreeDataStore>(name,title,_vars,wgtVarName) ;
472 tstore = static_cast<RooTreeDataStore*>(_dstore.get());
473 } else if (defaultStorageType==Vector) {
474 if (wgtVarName && newWeight) {
475 RooAbsArg* wgttmp = _vars.find(wgtVarName) ;
476 if (wgttmp) {
477 wgttmp->setAttribute("NewWeight") ;
478 }
479 }
480 _dstore = std::make_unique<RooVectorDataStore>(name,title,_vars,wgtVarName) ;
481 }
482
483
484 // Make import mapping if index category is specified
485 std::map<string,RooAbsData*> hmap ;
486 if (indexCat) {
487 auto hiter = impSliceData.begin() ;
488 for (const auto& token : ROOT::Split(impSliceNames, ",")) {
489 hmap[token] = static_cast<RooDataSet*>(*hiter);
490 ++hiter;
491 }
492 }
493
494 // process StoreError requests
495 if (errorSet) {
496 std::unique_ptr<RooArgSet> intErrorSet{static_cast<RooArgSet*>(_vars.selectCommon(*errorSet))};
497 intErrorSet->setAttribAll("StoreError") ;
498 for(RooAbsArg* arg : *intErrorSet) {
499 arg->attachToStore(*_dstore) ;
500 }
501 }
502 if (asymErrorSet) {
503 std::unique_ptr<RooArgSet> intAsymErrorSet{static_cast<RooArgSet*>(_vars.selectCommon(*asymErrorSet))};
504 intAsymErrorSet->setAttribAll("StoreAsymError") ;
505 for(RooAbsArg* arg : *intAsymErrorSet) {
506 arg->attachToStore(*_dstore) ;
507 }
508 }
509
510 appendToDir(this,true) ;
511
512 // Initialize RooDataSet with optional weight variable
513 initialize(wgtVarName);
514
515 // Import one or more datasets
516 std::unique_ptr<RooFormulaVar> cutVarTmp;
517
518 if (indexCat) {
519 // Case 2 --- Import multiple RooDataSets as slices
520 loadValuesFromSlices(*indexCat, hmap, cutRange, cutVar, cutSpec);
521 } else if (impData) {
522 // Case 3 --- Import RooDataSet
523 std::unique_ptr<RooDataSet> impDataSet;
524
525 // If we are importing a RooDataHist, first convert it to a RooDataSet
526 if(impData->InheritsFrom(RooDataHist::Class())) {
527 impDataSet = makeDataSetFromDataHist(static_cast<RooDataHist const &>(*impData));
528 impData = impDataSet.get();
529 }
530 if (cutSpec) {
531 cutVarTmp = std::make_unique<RooFormulaVar>(cutSpec, cutSpec, *impData->get());
532 cutVar = cutVarTmp.get();
533 }
534 _dstore->loadValues(impData->store(), cutVar, cutRange);
535
536 } else if (impTree || (fname && strlen(fname))) {
537 // Case 4 --- Import TTree from memory / file
538 std::unique_ptr<TFile> file;
539
540 if (impTree == nullptr) {
541 file.reset(TFile::Open(fname));
542 if (!file) {
543 std::stringstream ss;
544 ss << "RooDataSet::ctor(" << GetName() << ") ERROR file '" << fname
545 << "' cannot be opened or does not exist";
546 const std::string errMsg = ss.str();
547 coutE(InputArguments) << errMsg << std::endl;
548 throw std::invalid_argument(errMsg);
549 }
550
551 file->GetObject(tname, impTree);
552 if (!impTree) {
553 std::stringstream ss;
554 ss << "RooDataSet::ctor(" << GetName() << ") ERROR file '" << fname
555 << "' does not contain a TTree named '" << tname << "'";;
556 const std::string errMsg = ss.str();
557 coutE(InputArguments) << errMsg << std::endl;
558 throw std::invalid_argument(errMsg);
559 }
560 }
561
562 if (cutSpec) {
563 cutVarTmp = std::make_unique<RooFormulaVar>(cutSpec, cutSpec, _vars);
564 cutVar = cutVarTmp.get();
565 }
566
567 if (tstore) {
568 tstore->loadValues(impTree, cutVar, cutRange);
569 } else {
570 RooTreeDataStore tmpstore(name, title, _vars, wgtVarName);
571 tmpstore.loadValues(impTree, cutVar, cutRange);
572 _dstore->append(tmpstore);
573 }
574 }
575}
576
577
578
579////////////////////////////////////////////////////////////////////////////////
580/// Constructor of an empty data set from a RooArgSet defining the dimensions
581/// of the data space.
582/// \deprecated Use the more explicit `RooDataSet(name, title, vars, RooFit::WeightVar(wgtVarName))`.
583
584RooDataSet::RooDataSet(RooStringView name, RooStringView title, const RooArgSet& vars, const char* wgtVarName)
585 : RooDataSet(name,title,vars, RooFit::WeightVar(wgtVarName))
586{
587}
588
589
590////////////////////////////////////////////////////////////////////////////////
591/// Constructor of a data set from (part of) an existing data
592/// set. The dimensions of the data set are defined by the 'vars'
593/// RooArgSet, which can be identical to 'dset' dimensions, or a
594/// subset thereof. The 'cuts' string is an optional RooFormula
595/// expression and can be used to select the subset of the data
596/// points in 'dset' to be copied. The cut expression can refer to
597/// any variable in the source dataset. For cuts involving variables
598/// other than those contained in the source data set, such as
599/// intermediate formula objects, use the equivalent constructor
600/// accepting RooFormulaVar reference as cut specification.
601///
602/// For most uses the RooAbsData::reduce() wrapper function, which
603/// uses this constructor, is the most convenient way to create a
604/// subset of an existing data
605
607 const RooArgSet& vars, const char *cuts, const char* wgtVarName) :
608 RooAbsData(name,title,vars)
609{
610 // Initialize datastore
611 if(defaultStorageType == Tree) {
612 _dstore = std::make_unique<RooTreeDataStore>(name,title,_vars,*dset->_dstore,cuts,wgtVarName);
613 } else {
614 std::unique_ptr<RooFormulaVar> cutVar;
615 if (cuts && strlen(cuts) != 0) {
616 // Create a RooFormulaVar cut from given cut expression
617 cutVar = std::make_unique<RooFormulaVar>(cuts, cuts, _vars, /*checkVariables=*/false);
618 }
619 _dstore = std::make_unique<RooVectorDataStore>(name,title,
620 /*tds=*/*dset->_dstore,
621 /*vars=*/_vars,
622 /*cutVar=*/cutVar.get(),
623 /*cutRange=*/nullptr,
624 /*nStart=*/0,
625 /*nStop=*/dset->numEntries(),
626 /*wgtVarName=*/wgtVarName);
627 }
628
629 appendToDir(this,true) ;
630
631 if (wgtVarName) {
632 // Use the supplied weight column
633 initialize(wgtVarName) ;
634 } else {
635 if (dset->_wgtVar && vars.find(dset->_wgtVar->GetName())) {
636 // Use the weight column of the source data set
637 initialize(dset->_wgtVar->GetName()) ;
638 } else {
639 initialize(nullptr);
640 }
641 }
643}
644
645
646////////////////////////////////////////////////////////////////////////////////
647/// Constructor of a data set from (part of) an existing data
648/// set. The dimensions of the data set are defined by the 'vars'
649/// RooArgSet, which can be identical to 'dset' dimensions, or a
650/// subset thereof. The 'cutVar' formula variable is used to select
651/// the subset of data points to be copied. For subsets without
652/// selection on the data points, or involving cuts operating
653/// exclusively and directly on the data set dimensions, the
654/// equivalent constructor with a string based cut expression is
655/// recommended.
656///
657/// For most uses the RooAbsData::reduce() wrapper function, which
658/// uses this constructor, is the most convenient way to create a
659/// subset of an existing data
660
662 const RooArgSet& vars, const RooFormulaVar& cutVar, const char* wgtVarName)
663 : RooDataSet{name, title, dset, vars, cutVar.expression(), wgtVarName} {}
664
665
666
667////////////////////////////////////////////////////////////////////////////////
668/// Constructor of a data set from (part of) an ROOT TTree. The dimensions
669/// of the data set are defined by the 'vars' RooArgSet. For each dimension
670/// specified, the TTree must have a branch with the same name. For category
671/// branches, this branch should contain the numeric index value. Real dimensions
672/// can be constructed from either 'double' or 'Float_t' tree branches. In the
673/// latter case, an automatic conversion is applied.
674///
675/// The 'cutVar' formula variable
676/// is used to select the subset of data points to be copied.
677/// For subsets without selection on the data points, or involving cuts
678/// operating exclusively and directly on the data set dimensions, the equivalent
679/// constructor with a string based cut expression is recommended.
680
682 const RooArgSet& vars, const RooFormulaVar& cutVar, const char* wgtVarName)
683 : RooDataSet{name, title, theTree, vars, cutVar.expression(), wgtVarName} {}
684
685
686
687////////////////////////////////////////////////////////////////////////////////
688/// Constructor of a data set from (part of) a ROOT TTree.
689///
690/// \param[in] name Name of this dataset.
691/// \param[in] title Title for e.g. plotting.
692/// \param[in] theTree Tree to be imported.
693/// \param[in] vars Defines the columns of the data set. For each dimension
694/// specified, the TTree must have a branch with the same name. For category
695/// branches, this branch should contain the numeric index value. Real dimensions
696/// can be constructed from either 'double' or 'Float_t' tree branches. In the
697/// latter case, an automatic conversion is applied.
698/// \param[in] cuts Optional RooFormula expression to select the subset of the data points
699/// to be imported. The cut expression can refer to any variable in `vars`.
700/// \warning The expression only evaluates variables that are also in `vars`.
701/// Passing e.g.
702/// ```
703/// RooDataSet("data", "data", tree, RooArgSet(x), "x>y")
704/// ```
705/// Will load `x` from the tree, but leave `y` at an undefined value.
706/// If other expressions are needed, such as intermediate formula objects, use
707/// RooDataSet::RooDataSet(const char*,const char*,TTree*,const RooArgSet&,const RooFormulaVar&,const char*)
708/// \param[in] wgtVarName Name of the variable in `vars` that represents an event weight.
710 const RooArgSet& vars, const char* cuts, const char* wgtVarName) :
711 RooAbsData(name,title,vars)
712{
713 // Create tree version of datastore
714 auto tstore = std::make_unique<RooTreeDataStore>(name,title,_vars,*theTree,cuts,wgtVarName);
715
716 // Convert to vector datastore if needed
718 _dstore = std::move(tstore);
719 } else if (defaultStorageType==Vector) {
720 _dstore = std::make_unique<RooVectorDataStore>(name,title,_vars,wgtVarName);
721 static_cast<RooVectorDataStore&>(*_dstore).append(*tstore) ;
722 }
723
724 appendToDir(this,true) ;
725
726 initialize(wgtVarName) ;
728}
729
730
731
732////////////////////////////////////////////////////////////////////////////////
733/// Copy constructor
734
735RooDataSet::RooDataSet(RooDataSet const & other, const char* newname) :
736 RooAbsData(other,newname), RooDirItem()
737{
738 appendToDir(this,true) ;
739 initialize(other._wgtVar?other._wgtVar->GetName():nullptr);
741}
742
743////////////////////////////////////////////////////////////////////////////////
744/// Protected constructor for internal use only
745
747 const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
748 std::size_t nStart, std::size_t nStop) :
749 RooAbsData(name,title,vars)
750{
751 _dstore = dset->_dstore->reduce(name, title, _vars, cutVar, cutRange, nStart, nStop);
752
753 _cachedVars.add(_dstore->cachedVars());
754
755 appendToDir(this, true);
756 initialize(dset->_wgtVar ? dset->_wgtVar->GetName() : nullptr);
758}
759
760
761////////////////////////////////////////////////////////////////////////////////
762/// Return an empty clone of this dataset. If vars is not null, only the variables in vars
763/// are added to the definition of the empty clone
764
765RooAbsData* RooDataSet::emptyClone(const char* newName, const char* newTitle, const RooArgSet* vars, const char* wgtVarName) const
766{
767 bool useOldWeight = _wgtVar && (wgtVarName == nullptr || strcmp(wgtVarName, _wgtVar->GetName()) == 0);
768
769 if(newName == nullptr) newName = GetName();
770 if(newTitle == nullptr) newTitle = GetTitle();
771 if(useOldWeight) wgtVarName = _wgtVar->GetName();
772
773 RooArgSet vars2;
774 if(vars == nullptr) {
775 vars2.add(_vars);
776 } else {
777 for(RooAbsArg *var : *vars) {
778 // We should take the variables from the original dataset if
779 // available, such that we can query the "StoreError" and
780 // "StoreAsymError" attributes.
781 auto varInData = _vars.find(*var);
782 vars2.add(varInData ? *varInData : *var);
783 }
784 // We also need to add the weight variable of the original dataset if
785 // it's not added yet, again to query the error attributes correctly.
786 if(useOldWeight && !vars2.find(wgtVarName)) vars2.add(*_wgtVar);
787 }
788
789 RooArgSet errorSet;
790 RooArgSet asymErrorSet;
791
792 for(RooAbsArg *var : vars2) {
793 if(var->getAttribute("StoreError")) errorSet.add(*var);;
794 if(var->getAttribute("StoreAsymError")) asymErrorSet.add(*var);;
795 }
796
797 using namespace RooFit;
798 return new RooDataSet(newName, newTitle, vars2, WeightVar(wgtVarName), StoreError(errorSet), StoreAsymError(asymErrorSet));
799}
800
801
802
803////////////////////////////////////////////////////////////////////////////////
804/// Initialize the dataset. If wgtVarName is not null, interpret the observable
805/// with that name as event weight
806
807void RooDataSet::initialize(const char* wgtVarName)
808{
811 _wgtVar = 0 ;
812 if (wgtVarName) {
813 RooAbsArg* wgt = _varsNoWgt.find(wgtVarName) ;
814 if (!wgt) {
815 coutE(DataHandling) << "RooDataSet::RooDataSet(" << GetName() << "): designated weight variable "
816 << wgtVarName << " not found in set of variables, no weighting will be assigned" << endl ;
817 throw std::invalid_argument("RooDataSet::initialize() weight variable could not be initialised.");
818 } else if (!dynamic_cast<RooRealVar*>(wgt)) {
819 coutE(DataHandling) << "RooDataSet::RooDataSet(" << GetName() << "): designated weight variable "
820 << wgtVarName << " is not of type RooRealVar, no weighting will be assigned" << endl ;
821 throw std::invalid_argument("RooDataSet::initialize() weight variable could not be initialised.");
822 } else {
823 _varsNoWgt.remove(*wgt) ;
824 _wgtVar = (RooRealVar*) wgt ;
825 }
826 }
827}
828
829
830
831////////////////////////////////////////////////////////////////////////////////
832/// Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods
833
834RooAbsData* RooDataSet::reduceEng(const RooArgSet& varSubset, const RooFormulaVar* cutVar, const char* cutRange,
835 std::size_t nStart, std::size_t nStop)
836{
837 checkInit() ;
838 RooArgSet tmp(varSubset) ;
839 if (_wgtVar) {
840 tmp.add(*_wgtVar) ;
841 }
842
843 if (!cutRange || strchr(cutRange,',')==0) {
844 return new RooDataSet(GetName(), GetTitle(), this, tmp, cutVar, cutRange, nStart, nStop) ;
845 } else {
846 // Composite case: multiple ranges
847 auto tokens = ROOT::Split(cutRange, ",");
848 if (RooHelpers::checkIfRangesOverlap(tmp, tokens)) {
849 std::stringstream errMsg;
850 errMsg << "Error in RooAbsData::reduce! The ranges " << cutRange << " are overlapping!";
851 throw std::runtime_error(errMsg.str());
852 }
853 RooDataSet * out = nullptr;
854 for (const auto& token : tokens) {
855 if(!out) {
856 out = new RooDataSet(GetName(), GetTitle(), this, tmp, cutVar, token.c_str(), nStart, nStop);
857 } else {
858 RooDataSet appendedData{GetName(), GetTitle(), this, tmp, cutVar, token.c_str(), nStart, nStop};
859 out->append(appendedData);
860 }
861 }
862 return out;
863 }
864}
865
866
867
868////////////////////////////////////////////////////////////////////////////////
869/// Destructor
870
872{
873 removeFromDir(this) ;
875}
876
877
878
879////////////////////////////////////////////////////////////////////////////////
880/// Return binned clone of this dataset
881
882RooDataHist* RooDataSet::binnedClone(const char* newName, const char* newTitle) const
883{
884 std::string title;
885 std::string name;
886 if (newName) {
887 name = newName ;
888 } else {
889 name = std::string(GetName()) + "_binned" ;
890 }
891 if (newTitle) {
892 title = newTitle ;
893 } else {
894 title = std::string(GetTitle()) + "_binned" ;
895 }
896
897 return new RooDataHist(name,title,*get(),*this) ;
898}
899
900
901
902////////////////////////////////////////////////////////////////////////////////
903/// Return event weight of current event
904
905double RooDataSet::weight() const
906{
907 return store()->weight() ;
908}
909
910
911
912////////////////////////////////////////////////////////////////////////////////
913/// Return squared event weight of the current event. If this RooDataSet has no
914/// weight errors set, this will be the same as `weight() * weight()`, like
915/// expected for an unbinned dataset. When weight errors are set, it is assumed
916/// that the RooDataSet represents a weighted binned dataset and
917/// weightSquared() is the corresponding sum of weight squares for the bin.
918
920{
921 const double w = store()->weight();
922 const double e = weightError();
923 return e > 0.0 ? e * e : w * w;
924}
925
926
927////////////////////////////////////////////////////////////////////////////////
928/// \see RooAbsData::getWeightBatch().
929RooSpan<const double> RooDataSet::getWeightBatch(std::size_t first, std::size_t len, bool sumW2 /*=false*/) const {
930
931 std::size_t nEntries = this->numEntries(); // for the casting to std::size_t
932
933 if(first >= nEntries || (first + len) > nEntries) {
934 throw std::runtime_error("RooDataSet::getWeightBatch(): requested range not valid for dataset.");
935 }
936
937 RooSpan<const double> allWeights = _dstore->getWeightBatch(0, numEntries());
938 if(allWeights.empty()) return {};
939
940 if(!sumW2) return {std::cbegin(allWeights) + first, std::cbegin(allWeights) + first + len};
941
942 // Treat the sumW2 case with a result buffer, first reset buffer if the
943 // number of entries doesn't match with the dataset anymore
944 if(_sumW2Buffer && _sumW2Buffer->size() != nEntries) _sumW2Buffer.reset(nullptr);
945
946 if (!_sumW2Buffer) {
947 _sumW2Buffer = std::make_unique<std::vector<double>>();
948 _sumW2Buffer->reserve(nEntries);
949
950 for (std::size_t i = 0; i < nEntries; ++i) {
951 get(i);
952 _sumW2Buffer->push_back(weightSquared());
953 }
954 }
955
956 return RooSpan<const double>(_sumW2Buffer->begin() + first, _sumW2Buffer->begin() + first + len);
957}
958
959
960////////////////////////////////////////////////////////////////////////////////
961/// \copydoc RooAbsData::weightError(double&,double&,RooAbsData::ErrorType) const
962/// \param etype error type
963void RooDataSet::weightError(double& lo, double& hi, ErrorType etype) const
964{
965 store()->weightError(lo,hi,etype) ;
966}
967
968
969////////////////////////////////////////////////////////////////////////////////
970/// \copydoc RooAbsData::weightError(ErrorType)
971/// \param etype error type
973{
974 return store()->weightError(etype) ;
975}
976
977
978////////////////////////////////////////////////////////////////////////////////
979/// Return RooArgSet with coordinates of event 'index'
980
982{
983 const RooArgSet* ret = RooAbsData::get(index) ;
984 return ret ? &_varsNoWgt : 0 ;
985}
986
987
988////////////////////////////////////////////////////////////////////////////////
989
991{
992 return store()->sumEntries() ;
993}
994
995
996////////////////////////////////////////////////////////////////////////////////
997/// Return the sum of weights in all entries matching cutSpec (if specified)
998/// and in named range cutRange (if specified)
999
1000double RooDataSet::sumEntries(const char* cutSpec, const char* cutRange) const
1001{
1002 // Setup RooFormulaVar for cutSpec if it is present
1003 std::unique_ptr<RooFormula> select = nullptr ;
1004 if (cutSpec && strlen(cutSpec) > 0) {
1005 select = std::make_unique<RooFormula>("select",cutSpec,*get()) ;
1006 }
1007
1008 // Shortcut for unweighted unselected datasets
1009 if (!select && !cutRange && !isWeighted()) {
1010 return numEntries() ;
1011 }
1012
1013 // Otherwise sum the weights in the event
1015 for (int i = 0 ; i<numEntries() ; i++) {
1016 get(i) ;
1017 if (select && select->eval()==0.) continue ;
1018 if (cutRange && !_vars.allInRange(cutRange)) continue ;
1019 sumw += weight();
1020 }
1021
1022 return sumw.Sum() ;
1023}
1024
1025
1026
1027
1028////////////////////////////////////////////////////////////////////////////////
1029/// Return true if dataset contains weighted events
1030
1032{
1033 return store() ? store()->isWeighted() : false;
1034}
1035
1036
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Returns true if histogram contains bins with entries with a non-integer weight
1040
1042{
1043 // Return false if we have no weights
1044 if (!_wgtVar) return false ;
1045
1046 // Now examine individual weights
1047 for (int i=0 ; i<numEntries() ; i++) {
1048 get(i) ;
1049 if (std::abs(weight()-Int_t(weight()))>1e-10) return true ;
1050 }
1051 // If sum of weights is less than number of events there are negative (integer) weights
1052 if (sumEntries()<numEntries()) return true ;
1053
1054 return false ;
1055}
1056
1057
1058
1059
1060////////////////////////////////////////////////////////////////////////////////
1061/// Return a RooArgSet with the coordinates of the current event
1062
1064{
1065 return &_varsNoWgt ;
1066}
1067
1068
1069
1070////////////////////////////////////////////////////////////////////////////////
1071/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1072/// Any variables present in 'data' but not in the dataset will be silently ignored.
1073/// \param[in] data Data point.
1074/// \param[in] wgt Event weight. Defaults to 1. The current value of the weight variable is
1075/// ignored.
1076/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1077/// \param[in] wgtError Optional weight error.
1078/// \note This requires including the weight variable in the set of `StoreError` variables when constructing
1079/// the dataset.
1080
1081void RooDataSet::add(const RooArgSet& data, double wgt, double wgtError)
1082{
1083 checkInit() ;
1084
1085 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1086
1088
1089 if (_wgtVar) {
1090 _wgtVar->setVal(wgt) ;
1091 if (wgtError!=0.) {
1092 _wgtVar->setError(wgtError) ;
1093 }
1094 } else if ((wgt != 1. || wgtError != 0.) && _errorMsgCount < 5) {
1095 ccoutE(DataHandling) << "An event weight/error was passed but no weight variable was defined"
1096 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1098 }
1099
1101 && wgtError != 0.
1102 && std::abs(wgt*wgt - wgtError)/wgtError > 1.E-15 //Exception for standard wgt^2 errors, which need not be stored.
1103 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreError")) {
1104 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1105 << "', but the weight variable '" << _wgtVar->GetName()
1106 << "' does not store errors. Check `StoreError` in the RooDataSet constructor." << std::endl;
1108 }
1109
1110 fill();
1111
1112 // Restore weight state
1113 if (_wgtVar) {
1114 _wgtVar->setVal(oldW);
1116 }
1117}
1118
1119
1120
1121
1122////////////////////////////////////////////////////////////////////////////////
1123/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1124/// Any variables present in 'data' but not in the dataset will be silently ignored.
1125/// \param[in] indata Data point.
1126/// \param[in] inweight Event weight. The current value of the weight variable is ignored.
1127/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1128/// \param[in] weightErrorLo Asymmetric weight error.
1129/// \param[in] weightErrorHi Asymmetric weight error.
1130/// \note This requires including the weight variable in the set of `StoreAsymError` variables when constructing
1131/// the dataset.
1132
1133void RooDataSet::add(const RooArgSet& indata, double inweight, double weightErrorLo, double weightErrorHi)
1134{
1135 checkInit() ;
1136
1137 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1138
1139 _varsNoWgt.assign(indata);
1140 if (_wgtVar) {
1141 _wgtVar->setVal(inweight) ;
1142 _wgtVar->setAsymError(weightErrorLo,weightErrorHi) ;
1143 } else if (inweight != 1. && _errorMsgCount < 5) {
1144 ccoutE(DataHandling) << "An event weight was given but no weight variable was defined"
1145 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1147 }
1148
1150 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreAsymError")) {
1151 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1152 << "', but the weight variable '" << _wgtVar->GetName()
1153 << "' does not store errors. Check `StoreAsymError` in the RooDataSet constructor." << std::endl;
1155 }
1156
1157 fill();
1158
1159 // Restore weight state
1160 if (_wgtVar) {
1161 _wgtVar->setVal(oldW);
1163 }
1164}
1165
1166
1167
1168
1169
1170////////////////////////////////////////////////////////////////////////////////
1171/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1172/// \attention The order and type of the input variables are **assumed** to be the same as
1173/// for the RooArgSet returned by RooDataSet::get(). Input values will just be written
1174/// into the internal data columns by ordinal position.
1175/// \param[in] data Data point.
1176/// \param[in] wgt Event weight. Defaults to 1. The current value of the weight variable is
1177/// ignored.
1178/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1179/// \param[in] wgtError Optional weight error.
1180/// \note This requires including the weight variable in the set of `StoreError` variables when constructing
1181/// the dataset.
1182
1183void RooDataSet::addFast(const RooArgSet& data, double wgt, double wgtError)
1184{
1185 checkInit() ;
1186
1187 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1188
1189 _varsNoWgt.assignFast(data,_dstore->dirtyProp());
1190 if (_wgtVar) {
1191 _wgtVar->setVal(wgt) ;
1192 if (wgtError!=0.) {
1193 _wgtVar->setError(wgtError) ;
1194 }
1195 } else if (wgt != 1. && _errorMsgCount < 5) {
1196 ccoutE(DataHandling) << "An event weight was given but no weight variable was defined"
1197 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1199 }
1200
1201 fill();
1202
1204 && wgtError != 0. && wgtError != wgt*wgt //Exception for standard weight error, which need not be stored
1205 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreError")) {
1206 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1207 << "', but the weight variable '" << _wgtVar->GetName()
1208 << "' does not store errors. Check `StoreError` in the RooDataSet constructor." << std::endl;
1210 }
1212 _doWeightErrorCheck = false;
1213 }
1214
1215 if (_wgtVar) {
1216 _wgtVar->setVal(oldW);
1218 }
1219}
1220
1221
1222
1223////////////////////////////////////////////////////////////////////////////////
1224
1226 RooDataSet* data4, RooDataSet* data5, RooDataSet* data6)
1227{
1228 checkInit() ;
1229 list<RooDataSet*> dsetList ;
1230 if (data1) dsetList.push_back(data1) ;
1231 if (data2) dsetList.push_back(data2) ;
1232 if (data3) dsetList.push_back(data3) ;
1233 if (data4) dsetList.push_back(data4) ;
1234 if (data5) dsetList.push_back(data5) ;
1235 if (data6) dsetList.push_back(data6) ;
1236 return merge(dsetList) ;
1237}
1238
1239
1240
1241////////////////////////////////////////////////////////////////////////////////
1242/// Merge columns of supplied data set(s) with this data set. All
1243/// data sets must have equal number of entries. In case of
1244/// duplicate columns the column of the last dataset in the list
1245/// prevails
1246
1247bool RooDataSet::merge(list<RooDataSet*>dsetList)
1248{
1249
1250 checkInit() ;
1251 // Sanity checks: data sets must have the same size
1252 for (list<RooDataSet*>::iterator iter = dsetList.begin() ; iter != dsetList.end() ; ++iter) {
1253 if (numEntries()!=(*iter)->numEntries()) {
1254 coutE(InputArguments) << "RooDataSet::merge(" << GetName() << ") ERROR: datasets have different size" << endl ;
1255 return true ;
1256 }
1257 }
1258
1259 // Extend vars with elements of other dataset
1260 list<RooAbsDataStore*> dstoreList ;
1261 for (list<RooDataSet*>::iterator iter = dsetList.begin() ; iter != dsetList.end() ; ++iter) {
1262 _vars.addClone((*iter)->_vars,true) ;
1263 dstoreList.push_back((*iter)->store()) ;
1264 }
1265
1266 // Merge data stores
1267 RooAbsDataStore* mergedStore = _dstore->merge(_vars,dstoreList) ;
1268 mergedStore->SetName(_dstore->GetName()) ;
1269 mergedStore->SetTitle(_dstore->GetTitle()) ;
1270
1271 // Replace current data store with merged store
1272 _dstore.reset(mergedStore);
1273
1275 return false ;
1276}
1277
1278
1279////////////////////////////////////////////////////////////////////////////////
1280/// Add all data points of given data set to this data set.
1281/// Observable in 'data' that are not in this dataset
1282/// with not be transferred
1283
1285{
1286 checkInit() ;
1287 _dstore->append(*data._dstore) ;
1288}
1289
1290
1291
1292////////////////////////////////////////////////////////////////////////////////
1293/// Add a column with the values of the given (function) argument
1294/// to this dataset. The function value is calculated for each
1295/// event using the observable values of each event in case the
1296/// function depends on variables with names that are identical
1297/// to the observable names in the dataset
1298
1300{
1301 checkInit() ;
1302 RooAbsArg* ret = _dstore->addColumn(var,adjustRange) ;
1303 _vars.addOwned(*ret) ;
1305 return ret ;
1306}
1307
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Add a column with the values of the given list of (function)
1311/// argument to this dataset. Each function value is calculated for
1312/// each event using the observable values of the event in case the
1313/// function depends on variables with names that are identical to
1314/// the observable names in the dataset
1315
1317{
1318 auto * holderSet = new RooArgSet{};
1319 for(RooAbsArg * var : varList) {
1320 holderSet->add(*addColumn(*var));
1321 }
1322 return holderSet;
1323}
1324
1325
1326
1327
1328
1329////////////////////////////////////////////////////////////////////////////////
1330/// Special plot method for 'X-Y' datasets used in \f$ \chi^2 \f$ fitting.
1331/// For general plotting, see RooAbsData::plotOn().
1332///
1333/// These datasets
1334/// have one observable (X) and have weights (Y) and associated errors.
1335/// <table>
1336/// <tr><th> Contents options <th> Effect
1337/// <tr><td> YVar(RooRealVar& var) <td> Designate specified observable as 'y' variable
1338/// If not specified, the event weight will be the y variable
1339/// <tr><th> Histogram drawing options <th> Effect
1340/// <tr><td> DrawOption(const char* opt) <td> Select ROOT draw option for resulting TGraph object
1341/// <tr><td> LineStyle(Int_t style) <td> Select line style by ROOT line style code, default is solid
1342/// <tr><td> LineColor(Int_t color) <td> Select line color by ROOT color code, default is black
1343/// <tr><td> LineWidth(Int_t width) <td> Select line with in pixels, default is 3
1344/// <tr><td> MarkerStyle(Int_t style) <td> Select the ROOT marker style, default is 21
1345/// <tr><td> MarkerColor(Int_t color) <td> Select the ROOT marker color, default is black
1346/// <tr><td> MarkerSize(double size) <td> Select the ROOT marker size
1347/// <tr><td> Rescale(double factor) <td> Apply global rescaling factor to histogram
1348/// <tr><th> Misc. other options <th> Effect
1349/// <tr><td> Name(const chat* name) <td> Give curve specified name in frame. Useful if curve is to be referenced later
1350/// <tr><td> Invisible(bool flag) <td> Add curve to frame, but do not display. Useful in combination AddTo()
1351/// </table>
1352
1353RooPlot* RooDataSet::plotOnXY(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
1354 const RooCmdArg& arg3, const RooCmdArg& arg4,
1355 const RooCmdArg& arg5, const RooCmdArg& arg6,
1356 const RooCmdArg& arg7, const RooCmdArg& arg8) const
1357{
1358 checkInit() ;
1359
1360 RooLinkedList argList ;
1361 argList.Add((TObject*)&arg1) ; argList.Add((TObject*)&arg2) ;
1362 argList.Add((TObject*)&arg3) ; argList.Add((TObject*)&arg4) ;
1363 argList.Add((TObject*)&arg5) ; argList.Add((TObject*)&arg6) ;
1364 argList.Add((TObject*)&arg7) ; argList.Add((TObject*)&arg8) ;
1365
1366 // Process named arguments
1367 RooCmdConfig pc(Form("RooDataSet::plotOnXY(%s)",GetName())) ;
1368 pc.defineString("drawOption","DrawOption",0,"P") ;
1369 pc.defineString("histName","Name",0,"") ;
1370 pc.defineInt("lineColor","LineColor",0,-999) ;
1371 pc.defineInt("lineStyle","LineStyle",0,-999) ;
1372 pc.defineInt("lineWidth","LineWidth",0,-999) ;
1373 pc.defineInt("markerColor","MarkerColor",0,-999) ;
1374 pc.defineInt("markerStyle","MarkerStyle",0,8) ;
1375 pc.defineDouble("markerSize","MarkerSize",0,-999) ;
1376 pc.defineInt("fillColor","FillColor",0,-999) ;
1377 pc.defineInt("fillStyle","FillStyle",0,-999) ;
1378 pc.defineInt("histInvisible","Invisible",0,0) ;
1379 pc.defineDouble("scaleFactor","Rescale",0,1.) ;
1380 pc.defineObject("xvar","XVar",0,0) ;
1381 pc.defineObject("yvar","YVar",0,0) ;
1382
1383
1384 // Process & check varargs
1385 pc.process(argList) ;
1386 if (!pc.ok(true)) {
1387 return frame ;
1388 }
1389
1390 // Extract values from named arguments
1391 const char* drawOptions = pc.getString("drawOption") ;
1392 Int_t histInvisible = pc.getInt("histInvisible") ;
1393 const char* histName = pc.getString("histName",0,true) ;
1394 double scaleFactor = pc.getDouble("scaleFactor") ;
1395
1396 RooRealVar* xvar = (RooRealVar*) _vars.find(frame->getPlotVar()->GetName()) ;
1397
1398 // Determine Y variable (default is weight, if present)
1399 RooRealVar* yvar = (RooRealVar*)(pc.getObject("yvar")) ;
1400
1401 // Sanity check. XY plotting only applies to weighted datasets if no YVar is specified
1402 if (!_wgtVar && !yvar) {
1403 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR: no YVar() argument specified and dataset is not weighted" << endl ;
1404 return 0 ;
1405 }
1406
1407 RooRealVar* dataY = yvar ? (RooRealVar*) _vars.find(yvar->GetName()) : 0 ;
1408 if (yvar && !dataY) {
1409 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR on YVar() argument, dataset does not contain a variable named " << yvar->GetName() << endl ;
1410 return 0 ;
1411 }
1412
1413
1414 // Make RooHist representing XY contents of data
1415 RooHist* graph = new RooHist ;
1416 if (histName) {
1417 graph->SetName(histName) ;
1418 } else {
1419 graph->SetName(Form("hxy_%s",GetName())) ;
1420 }
1421
1422 for (int i=0 ; i<numEntries() ; i++) {
1423 get(i) ;
1424 double x = xvar->getVal() ;
1425 double exlo = xvar->getErrorLo() ;
1426 double exhi = xvar->getErrorHi() ;
1427 double y,eylo,eyhi ;
1428 if (!dataY) {
1429 y = weight() ;
1430 weightError(eylo,eyhi) ;
1431 } else {
1432 y = dataY->getVal() ;
1433 eylo = dataY->getErrorLo() ;
1434 eyhi = dataY->getErrorHi() ;
1435 }
1436 graph->addBinWithXYError(x,y,-1*exlo,exhi,-1*eylo,eyhi,scaleFactor) ;
1437 }
1438
1439 // Adjust style options according to named arguments
1440 Int_t lineColor = pc.getInt("lineColor") ;
1441 Int_t lineStyle = pc.getInt("lineStyle") ;
1442 Int_t lineWidth = pc.getInt("lineWidth") ;
1443 Int_t markerColor = pc.getInt("markerColor") ;
1444 Int_t markerStyle = pc.getInt("markerStyle") ;
1445 Size_t markerSize = pc.getDouble("markerSize") ;
1446 Int_t fillColor = pc.getInt("fillColor") ;
1447 Int_t fillStyle = pc.getInt("fillStyle") ;
1448
1449 if (lineColor!=-999) graph->SetLineColor(lineColor) ;
1450 if (lineStyle!=-999) graph->SetLineStyle(lineStyle) ;
1451 if (lineWidth!=-999) graph->SetLineWidth(lineWidth) ;
1452 if (markerColor!=-999) graph->SetMarkerColor(markerColor) ;
1453 if (markerStyle!=-999) graph->SetMarkerStyle(markerStyle) ;
1454 if (markerSize!=-999) graph->SetMarkerSize(markerSize) ;
1455 if (fillColor!=-999) graph->SetFillColor(fillColor) ;
1456 if (fillStyle!=-999) graph->SetFillStyle(fillStyle) ;
1457
1458 // Add graph to frame
1459 frame->addPlotable(graph,drawOptions,histInvisible) ;
1460
1461 return frame ;
1462}
1463
1464
1465
1466
1467////////////////////////////////////////////////////////////////////////////////
1468/// Read given list of ascii files, and construct a data set, using the given
1469/// ArgList as structure definition.
1470/// \param fileList Multiple file names, comma separated. Each
1471/// file is optionally prefixed with 'commonPath' if such a path is
1472/// provided
1473///
1474/// \param varList Specify the dimensions of the dataset to be built.
1475/// This list describes the order in which these dimensions appear in the
1476/// ascii files to be read.
1477/// Each line in the ascii file should contain N white-space separated
1478/// tokens, with N the number of args in `varList`. Any text beyond
1479/// N tokens will be ignored with a warning message.
1480/// (NB: This is the default output of RooArgList::writeToStream())
1481///
1482/// \param verbOpt `Q` be quiet, `D` debug mode (verbose)
1483///
1484/// \param commonPath All filenames in `fileList` will be prefixed with this optional path.
1485///
1486/// \param indexCatName Interpret the data as belonging to category `indexCatName`.
1487/// When multiple files are read, a RooCategory arg in `varList` can
1488/// optionally be designated to hold information about the source file
1489/// of each data point. This feature is enabled by giving the name
1490/// of the (already existing) category variable in `indexCatName`.
1491///
1492/// \attention If the value of any of the variables on a given line exceeds the
1493/// fit range associated with that dimension, the entire line will be
1494/// ignored. A warning message is printed in each case, unless the
1495/// `Q` verbose option is given. The number of events read and skipped
1496/// is always summarized at the end.
1497///
1498/// If no further information is given a label name 'fileNNN' will
1499/// be assigned to each event, where NNN is the sequential number of
1500/// the source file in `fileList`.
1501///
1502/// Alternatively, it is possible to override the default label names
1503/// of the index category by specifying them in the fileList string:
1504/// When instead of `file1.txt,file2.txt` the string
1505/// `file1.txt:FOO,file2.txt:BAR` is specified, a state named "FOO"
1506/// is assigned to the index category for each event originating from
1507/// file1.txt. The labels FOO,BAR may be predefined in the index
1508/// category via defineType(), but don't have to be.
1509///
1510/// Finally, one can also assign the same label to multiple files,
1511/// either by specifying `file1.txt:FOO,file2,txt:FOO,file3.txt:BAR`
1512/// or `file1.txt,file2.txt:FOO,file3.txt:BAR`.
1513///
1514
1515RooDataSet *RooDataSet::read(const char *fileList, const RooArgList &varList,
1516 const char *verbOpt, const char* commonPath,
1517 const char* indexCatName) {
1518 // Make working copy of variables list
1519 RooArgList variables(varList) ;
1520
1521 // Append blinding state category to variable list if not already there
1522 bool ownIsBlind(true) ;
1523 RooAbsArg* blindState = variables.find("blindState") ;
1524 if (!blindState) {
1525 blindState = new RooCategory("blindState","Blinding State") ;
1526 variables.add(*blindState) ;
1527 } else {
1528 ownIsBlind = false ;
1529 if (blindState->IsA()!=RooCategory::Class()) {
1530 oocoutE(nullptr,DataHandling) << "RooDataSet::read: ERROR: variable list already contains"
1531 << "a non-RooCategory blindState member" << endl ;
1532 return 0 ;
1533 }
1534 oocoutW(nullptr,DataHandling) << "RooDataSet::read: WARNING: recycling existing "
1535 << "blindState category in variable list" << endl ;
1536 }
1537 RooCategory* blindCat = (RooCategory*) blindState ;
1538
1539 // Configure blinding state category
1540 blindCat->setAttribute("Dynamic") ;
1541 blindCat->defineType("Normal",0) ;
1542 blindCat->defineType("Blind",1) ;
1543
1544 // parse the option string
1545 TString opts= verbOpt;
1546 opts.ToLower();
1547 bool verbose= !opts.Contains("q");
1548 bool debug= opts.Contains("d");
1549
1550 auto data = std::make_unique<RooDataSet>("dataset", fileList, variables);
1551 if (ownIsBlind) { variables.remove(*blindState) ; delete blindState ; }
1552 if(!data) {
1553 oocoutE(nullptr,DataHandling) << "RooDataSet::read: unable to create a new dataset"
1554 << endl;
1555 return nullptr;
1556 }
1557
1558 // Redirect blindCat to point to the copy stored in the data set
1559 blindCat = (RooCategory*) data->_vars.find("blindState") ;
1560
1561 // Find index category, if requested
1562 RooCategory *indexCat = 0;
1563 //RooCategory *indexCatOrig = 0;
1564 if (indexCatName) {
1565 RooAbsArg* tmp = 0;
1566 tmp = data->_vars.find(indexCatName) ;
1567 if (!tmp) {
1568 oocoutE(data.get(),DataHandling) << "RooDataSet::read: no index category named "
1569 << indexCatName << " in supplied variable list" << endl ;
1570 return nullptr;
1571 }
1572 if (tmp->IsA()!=RooCategory::Class()) {
1573 oocoutE(data.get(),DataHandling) << "RooDataSet::read: variable " << indexCatName
1574 << " is not a RooCategory" << endl ;
1575 return nullptr;
1576 }
1577 indexCat = static_cast<RooCategory*>(tmp);
1578
1579 // Prevent RooArgSet from attempting to read in indexCat
1580 indexCat->setAttribute("Dynamic") ;
1581 }
1582
1583
1584 Int_t outOfRange(0) ;
1585
1586 // Loop over all names in comma separated list
1587 Int_t fileSeqNum(0);
1588 for (const auto& filename : ROOT::Split(std::string(fileList), ", ")) {
1589 // Determine index category number, if this option is active
1590 if (indexCat) {
1591
1592 // Find and detach optional file category name
1593 const char *catname = strchr(filename.c_str(),':');
1594
1595 if (catname) {
1596 // Use user category name if provided
1597 catname++ ;
1598
1599 if (indexCat->hasLabel(catname)) {
1600 // Use existing category index
1601 indexCat->setLabel(catname);
1602 } else {
1603 // Register cat name
1604 indexCat->defineType(catname,fileSeqNum) ;
1605 indexCat->setIndex(fileSeqNum) ;
1606 }
1607 } else {
1608 // Assign autogenerated name
1609 char newLabel[128] ;
1610 snprintf(newLabel,128,"file%03d",fileSeqNum) ;
1611 if (indexCat->defineType(newLabel,fileSeqNum)) {
1612 oocoutE(data.get(), DataHandling) << "RooDataSet::read: Error, cannot register automatic type name " << newLabel
1613 << " in index category " << indexCat->GetName() << endl ;
1614 return 0 ;
1615 }
1616 // Assign new category number
1617 indexCat->setIndex(fileSeqNum) ;
1618 }
1619 }
1620
1621 oocoutI(data.get(), DataHandling) << "RooDataSet::read: reading file " << filename << endl ;
1622
1623 // Prefix common path
1624 TString fullName(commonPath) ;
1625 fullName.Append(filename) ;
1626 ifstream file(fullName) ;
1627
1628 if (!file.good()) {
1629 oocoutE(data.get(), DataHandling) << "RooDataSet::read: unable to open '"
1630 << filename << "'. Returning nullptr now." << endl;
1631 return nullptr;
1632 }
1633
1634 // double value;
1635 Int_t line(0) ;
1636 bool haveBlindString(false) ;
1637
1638 while(file.good() && !file.eof()) {
1639 line++;
1640 if(debug) oocxcoutD(data.get(),DataHandling) << "reading line " << line << endl;
1641
1642 // process comment lines
1643 if (file.peek() == '#') {
1644 if(debug) oocxcoutD(data.get(),DataHandling) << "skipping comment on line " << line << endl;
1645 } else {
1646 // Read single line
1647 bool readError = variables.readFromStream(file,true,verbose) ;
1648 data->_vars.assign(variables) ;
1649
1650 // Stop on read error
1651 if(!file.good()) {
1652 oocoutE(data.get(), DataHandling) << "RooDataSet::read(static): read error at line " << line << endl ;
1653 break;
1654 }
1655
1656 if (readError) {
1657 outOfRange++ ;
1658 } else {
1659 blindCat->setIndex(haveBlindString) ;
1660 data->fill(); // store this event
1661 }
1662 }
1663
1664 // Skip all white space (including empty lines).
1665 while (isspace(file.peek())) {
1666 char dummy;
1667 file >> std::noskipws >> dummy >> std::skipws;
1668 }
1669 }
1670
1671 file.close();
1672
1673 // get next file name
1674 fileSeqNum++ ;
1675 }
1676
1677 if (indexCat) {
1678 // Copy dynamically defined types from new data set to indexCat in original list
1679 assert(dynamic_cast<RooCategory*>(variables.find(indexCatName)));
1680 const auto origIndexCat = static_cast<RooCategory*>(variables.find(indexCatName));
1681 for (const auto& nameIdx : *indexCat) {
1682 origIndexCat->defineType(nameIdx.first, nameIdx.second);
1683 }
1684 }
1685 oocoutI(data.get(),DataHandling) << "RooDataSet::read: read " << data->numEntries()
1686 << " events (ignored " << outOfRange << " out of range events)" << endl;
1687
1688 return data.release();
1689}
1690
1691
1692
1693
1694////////////////////////////////////////////////////////////////////////////////
1695/// Write the contents of this dataset to an ASCII file with the specified name.
1696/// Each event will be written as a single line containing the written values
1697/// of each observable in the order they were declared in the dataset and
1698/// separated by whitespaces
1699
1700bool RooDataSet::write(const char* filename) const
1701{
1702 // Open file for writing
1703 ofstream ofs(filename) ;
1704 if (ofs.fail()) {
1705 coutE(DataHandling) << "RooDataSet::write(" << GetName() << ") cannot create file " << filename << endl ;
1706 return true ;
1707 }
1708
1709 // Write all lines as arglist in compact mode
1710 coutI(DataHandling) << "RooDataSet::write(" << GetName() << ") writing ASCII file " << filename << endl ;
1711 return write(ofs);
1712}
1713
1714////////////////////////////////////////////////////////////////////////////////
1715/// Write the contents of this dataset to the stream.
1716/// Each event will be written as a single line containing the written values
1717/// of each observable in the order they were declared in the dataset and
1718/// separated by whitespaces
1719
1720bool RooDataSet::write(ostream & ofs) const {
1721 checkInit();
1722
1723 for (Int_t i=0; i<numEntries(); ++i) {
1724 get(i)->writeToStream(ofs,true);
1725 }
1726
1727 if (ofs.fail()) {
1728 coutW(DataHandling) << "RooDataSet::write(" << GetName() << "): WARNING error(s) have occured in writing" << endl ;
1729 }
1730
1731 return ofs.fail() ;
1732}
1733
1734
1735////////////////////////////////////////////////////////////////////////////////
1736/// Print info about this dataset to the specified output stream.
1737///
1738/// Standard: number of entries
1739/// Shape: list of variables we define & were generated with
1740
1741void RooDataSet::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
1742{
1743 checkInit() ;
1745 if (_wgtVar) {
1746 os << indent << " Dataset variable \"" << _wgtVar->GetName() << "\" is interpreted as the event weight" << endl ;
1747 }
1748}
1749
1750
1751////////////////////////////////////////////////////////////////////////////////
1752/// Print value of the dataset, i.e. the sum of weights contained in the dataset
1753
1754void RooDataSet::printValue(ostream& os) const
1755{
1756 os << numEntries() << " entries" ;
1757 if (isWeighted()) {
1758 os << " (" << sumEntries() << " weighted)" ;
1759 }
1760}
1761
1762
1763
1764////////////////////////////////////////////////////////////////////////////////
1765/// Print argument of dataset, i.e. the observable names
1766
1767void RooDataSet::printArgs(ostream& os) const
1768{
1769 os << "[" ;
1770 bool first(true) ;
1771 for(RooAbsArg* arg : _varsNoWgt) {
1772 if (first) {
1773 first=false ;
1774 } else {
1775 os << "," ;
1776 }
1777 os << arg->GetName() ;
1778 }
1779 if (_wgtVar) {
1780 os << ",weight:" << _wgtVar->GetName() ;
1781 }
1782 os << "]" ;
1783}
1784
1785
1786
1787////////////////////////////////////////////////////////////////////////////////
1788/// Change the name of this dataset into the given name
1789
1790void RooDataSet::SetName(const char *name)
1791{
1792 if (_dir) _dir->GetList()->Remove(this);
1793 // We need to use the function from RooAbsData, because it already overrides TNamed::SetName
1795 if (_dir) _dir->GetList()->Add(this);
1796}
1797
1798
1799////////////////////////////////////////////////////////////////////////////////
1800/// Change the title of this dataset into the given name
1801
1802void RooDataSet::SetNameTitle(const char *name, const char* title)
1803{
1804 SetName(name);
1805 SetTitle(title);
1806}
1807
1808
1809////////////////////////////////////////////////////////////////////////////////
1810/// Stream an object of class RooDataSet.
1811
1813{
1814 if (R__b.IsReading()) {
1815
1816 UInt_t R__s, R__c;
1817 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1818
1819 if (R__v>1) {
1820
1821 // Use new-style streaming for version >1
1822 R__b.ReadClassBuffer(RooDataSet::Class(),this,R__v,R__s,R__c);
1823
1824 } else {
1825
1826 // Legacy dataset conversion happens here. Legacy RooDataSet inherits from RooTreeData
1827 // which in turn inherits from RooAbsData. Manually stream RooTreeData contents on
1828 // file here and convert it into a RooTreeDataStore which is installed in the
1829 // new-style RooAbsData base class
1830
1831 // --- This is the contents of the streamer code of RooTreeData version 1 ---
1832 UInt_t R__s1, R__c1;
1833 Version_t R__v1 = R__b.ReadVersion(&R__s1, &R__c1); if (R__v1) { }
1834
1836 TTree* X_tree(0) ; R__b >> X_tree;
1837 RooArgSet X_truth ; X_truth.Streamer(R__b);
1838 TString X_blindString ; X_blindString.Streamer(R__b);
1839 R__b.CheckByteCount(R__s1, R__c1, TClass::GetClass("RooTreeData"));
1840 // --- End of RooTreeData-v1 streamer
1841
1842 // Construct RooTreeDataStore from X_tree and complete initialization of new-style RooAbsData
1843 _dstore = std::make_unique<RooTreeDataStore>(X_tree,_vars) ;
1844 _dstore->SetName(GetName()) ;
1845 _dstore->SetTitle(GetTitle()) ;
1846 _dstore->checkInit() ;
1847
1848 // This is the contents of the streamer code of RooDataSet version 1
1850 _varsNoWgt.Streamer(R__b);
1851 R__b >> _wgtVar;
1852 R__b.CheckByteCount(R__s, R__c, RooDataSet::IsA());
1853
1854
1855 }
1856 } else {
1858 }
1859}
1860
1861
1862
1863////////////////////////////////////////////////////////////////////////////////
1864/// Convert vector-based storage to tree-based storage. This implementation overrides the base class
1865/// implementation because the latter doesn't transfer weights.
1867{
1869 _dstore = std::make_unique<RooTreeDataStore>(GetName(), GetTitle(), _vars, *_dstore, nullptr, _wgtVar ? _wgtVar->GetName() : nullptr);
1871 }
1872}
1873
1874
1875namespace {
1876
1877 // Compile-time test if we can still use TStrings for the constructors of
1878 // RooDataClasses, either for both name and title or for only one of them.
1879 TString tstr = "tstr";
1880 const char * cstr = "cstr";
1881 RooRealVar x{"x", "x", 1.0};
1882 RooArgSet vars{x};
1883 RooDataSet d1(tstr, tstr, vars);
1884 RooDataSet d2(tstr, cstr, vars);
1885 RooDataSet d3(cstr, tstr, vars);
1886
1887} // namespace
1888
1889
1890void RooDataSet::loadValuesFromSlices(RooCategory &indexCat, std::map<std::string, RooAbsData *> const &slices,
1891 const char *rangeName, RooFormulaVar const *cutVar, const char *cutSpec)
1892{
1893
1894 if (cutVar && cutSpec) {
1895 throw std::invalid_argument("Only one of cutVar or cutSpec should be not a nullptr!");
1896 }
1897
1898 auto &indexCatInData = *static_cast<RooCategory *>(_vars.find(indexCat.GetName()));
1899
1900 for (auto const &item : slices) {
1901 std::unique_ptr<RooDataSet> sliceDataSet;
1902 RooAbsData* sliceData = item.second;
1903
1904 // If we are importing a RooDataHist, first convert it to a RooDataSet
1905 if(sliceData->InheritsFrom(RooDataHist::Class())) {
1906 sliceDataSet = makeDataSetFromDataHist(static_cast<RooDataHist const &>(*sliceData));
1907 sliceData = sliceDataSet.get();
1908 }
1909
1910 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
1911 if (!indexCat.hasLabel(item.first)) {
1912 indexCat.defineType(item.first);
1913 coutI(InputArguments) << "RooDataSet::ctor(" << GetName() << ") defining state \"" << item.first
1914 << "\" in index category " << indexCat.GetName() << std::endl;
1915 }
1916 if (!indexCatInData.hasLabel(item.first)) {
1917 indexCatInData.defineType(item.first);
1918 }
1919 indexCatInData.setLabel(item.first.c_str());
1920 std::unique_ptr<RooFormulaVar> cutVarTmp;
1921 if (cutSpec) {
1922 cutVarTmp = std::make_unique<RooFormulaVar>(cutSpec, cutSpec, *sliceData->get());
1923 cutVar = cutVarTmp.get();
1924 }
1925 _dstore->loadValues(sliceData->store(), cutVar, rangeName);
1926 }
1927}
#define e(i)
Definition: RSha256.hxx:103
#define coutI(a)
Definition: RooMsgService.h:34
#define ccoutE(a)
Definition: RooMsgService.h:45
#define oocoutW(o, a)
Definition: RooMsgService.h:51
#define oocxcoutD(o, a)
Definition: RooMsgService.h:87
#define coutW(a)
Definition: RooMsgService.h:36
#define oocoutE(o, a)
Definition: RooMsgService.h:52
#define oocoutI(o, a)
Definition: RooMsgService.h:49
#define coutE(a)
Definition: RooMsgService.h:37
#define TRACE_DESTROY
Definition: RooTrace.h:24
#define TRACE_CREATE
Definition: RooTrace.h:23
int Int_t
Definition: RtypesCore.h:45
float Size_t
Definition: RtypesCore.h:96
short Version_t
Definition: RtypesCore.h:65
#define ClassImp(name)
Definition: Rtypes.h:375
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 filename
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
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 bytes
char name[80]
Definition: TGX11.cxx:110
#define hi
Definition: THbookFile.cxx:128
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition: TString.cxx:2468
#define snprintf
Definition: civetweb.c:1540
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition: RooAbsArg.h:72
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:245
bool hasLabel(const std::string &label) const
Check if a state with name label exists.
virtual const char * getCurrentLabel() const
Return label string of current state.
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.
bool allInRange(const char *rangeSpec) const
Return true if all contained object report to have their value inside the specified range.
void assignFast(const RooAbsCollection &other, bool setValDirty=true) const
Functional equivalent of assign() but assumes this and other collection have same layout.
bool empty() const
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void setAttribAll(const Text_t *name, bool value=true)
Set given attribute in each element of the collection by calling each elements setAttribute() functio...
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...
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
virtual RooAbsArg * addClone(const RooAbsArg &var, bool silent=false)
Add a clone of the specified argument to list.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooAbsDataStore is the abstract base class for data collection that use a TTree as internal storage m...
virtual bool isWeighted() const =0
virtual double sumEntries() const
virtual double weightError(RooAbsData::ErrorType etype=RooAbsData::Poisson) const =0
virtual double weight() const =0
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:61
virtual const RooArgSet * get() const
Definition: RooAbsData.h:105
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Interface for detailed printing of object.
Definition: RooAbsData.cxx:866
void SetName(const char *name) override
Set the name of the TNamed.
RooAbsDataStore * store()
Definition: RooAbsData.h:81
void checkInit() const
static StorageType defaultStorageType
Definition: RooAbsData.h:321
std::unique_ptr< RooAbsDataStore > _dstore
Data storage implementation.
Definition: RooAbsData.h:360
virtual void fill()
Definition: RooAbsData.cxx:377
RooArgSet _vars
Dimensions of this data set.
Definition: RooAbsData.h:357
RooArgSet _cachedVars
! External variables cached with this data set
Definition: RooAbsData.h:358
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Definition: RooAbsData.cxx:384
StorageType storageType
Definition: RooAbsData.h:323
virtual bool isWeighted() const
Definition: RooAbsData.h:156
void Streamer(TBuffer &) override
Stream an object of class RooAbsData.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:105
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:56
void Streamer(TBuffer &) override
Stream an object of class TObject.
virtual void writeToStream(std::ostream &os, bool compact, const char *section=nullptr) const
Write the contents of the argset in ASCII form to given stream.
Definition: RooArgSet.cxx:347
RooCategory is an object to represent discrete states.
Definition: RooCategory.h:28
bool setIndex(Int_t index, bool printError=true) override
Set value by specifying the index code of the desired state.
bool defineType(const std::string &label)
Define a state with given name.
bool setLabel(const char *label, bool printError=true) override
Set value by specifying the name of the desired state.
static TClass * Class()
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:26
const char * getString(Int_t idx) const
Return string stored in slot idx.
Definition: RooCmdArg.h:95
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
Definition: RooCmdConfig.h:31
The RooDataHist is a container class to hold N-dimensional binned data.
Definition: RooDataHist.h:39
static TClass * Class()
double weight(std::size_t i) const
Return weight of i-th bin.
Definition: RooDataHist.h:104
double weightSquared(std::size_t i) const
Return squared weight sum of i-th bin.
Definition: RooDataHist.h:110
const RooArgSet * get() const override
Get bin centre of current bin.
Definition: RooDataHist.h:76
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:57
RooSpan< const double > getWeightBatch(std::size_t first, std::size_t len, bool sumW2) const override
Definition: RooDataSet.cxx:929
RooAbsData * emptyClone(const char *newName=nullptr, const char *newTitle=nullptr, const RooArgSet *vars=nullptr, const char *wgtVarName=nullptr) const override
Return an empty clone of this dataset.
Definition: RooDataSet.cxx:765
RooRealVar * _wgtVar
Pointer to weight variable (if set)
Definition: RooDataSet.h:174
bool _doWeightErrorCheck
! When adding events with weights, check that weights can actually be stored.
Definition: RooDataSet.h:186
static void cleanup()
Definition: RooDataSet.cxx:124
RooArgSet _varsNoWgt
Vars without weight variable.
Definition: RooDataSet.h:173
void loadValuesFromSlices(RooCategory &indexCat, std::map< std::string, RooAbsData * > const &slices, const char *rangeName, RooFormulaVar const *cutVar, const char *cutSpec)
void weightError(double &lo, double &hi, ErrorType etype=SumW2) const override
Return the asymmetric errors on the current weight.
Definition: RooDataSet.cxx:963
const RooArgSet * get() const override
Return a RooArgSet with the coordinates of the current event.
void initialize(const char *wgtVarName)
Initialize the dataset.
Definition: RooDataSet.cxx:807
void printArgs(std::ostream &os) const override
Print argument of dataset, i.e. the observable names.
void SetName(const char *name) override
Change the name of this dataset into the given name.
virtual void addFast(const RooArgSet &row, double weight=1.0, double weightError=0.0)
Add a data point, with its coordinates specified in the 'data' argset, to the data set.
bool merge(RooDataSet *data1, RooDataSet *data2=nullptr, RooDataSet *data3=nullptr, RooDataSet *data4=nullptr, RooDataSet *data5=nullptr, RooDataSet *data6=nullptr)
TClass * IsA() const override
Definition: RooDataSet.h:190
virtual RooAbsArg * addColumn(RooAbsArg &var, bool adjustRange=true)
Add a column with the values of the given (function) argument to this dataset.
bool write(const char *filename) const
Write the contents of this dataset to an ASCII file with the specified name.
double sumEntries() const override
Return effective number of entries in dataset, i.e., sum all weights.
Definition: RooDataSet.cxx:990
RooAbsData * reduceEng(const RooArgSet &varSubset, const RooFormulaVar *cutVar, const char *cutRange=nullptr, std::size_t nStart=0, std::size_t nStop=std::numeric_limits< std::size_t >::max()) override
Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods.
Definition: RooDataSet.cxx:834
virtual RooArgSet * addColumns(const RooArgList &varList)
Add a column with the values of the given list of (function) argument to this dataset.
~RooDataSet() override
Destructor.
Definition: RooDataSet.cxx:871
bool isNonPoissonWeighted() const override
Returns true if histogram contains bins with entries with a non-integer weight.
void SetNameTitle(const char *name, const char *title) override
Change the title of this dataset into the given name.
void printValue(std::ostream &os) const override
Print value of the dataset, i.e. the sum of weights contained in the dataset.
virtual RooPlot * plotOnXY(RooPlot *frame, const RooCmdArg &arg1=RooCmdArg::none(), const RooCmdArg &arg2=RooCmdArg::none(), const RooCmdArg &arg3=RooCmdArg::none(), const RooCmdArg &arg4=RooCmdArg::none(), const RooCmdArg &arg5=RooCmdArg::none(), const RooCmdArg &arg6=RooCmdArg::none(), const RooCmdArg &arg7=RooCmdArg::none(), const RooCmdArg &arg8=RooCmdArg::none()) const
Special plot method for 'X-Y' datasets used in fitting.
void append(RooDataSet &data)
Add all data points of given data set to this data set.
RooDataSet()
Default constructor for persistence.
Definition: RooDataSet.cxx:183
std::unique_ptr< std::vector< double > > _sumW2Buffer
! Buffer for sumW2 in case a batch of values is requested.
Definition: RooDataSet.h:188
void Streamer(TBuffer &) override
Stream an object of class RooDataSet.
void add(const RooArgSet &row, double weight, double weightError)
Add one ore more rows of data.
unsigned short _errorMsgCount
! Counter to silence error messages when filling dataset.
Definition: RooDataSet.h:185
static TClass * Class()
void convertToTreeStore() override
Convert vector-based storage to tree-based storage.
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print info about this dataset to the specified output stream.
RooDataHist * binnedClone(const char *newName=nullptr, const char *newTitle=nullptr) const
Return binned clone of this dataset.
Definition: RooDataSet.cxx:882
double weightSquared() const override
Return squared event weight of the current event.
Definition: RooDataSet.cxx:919
double weight() const override
Return event weight of current event.
Definition: RooDataSet.cxx:905
static RooDataSet * read(const char *filename, const RooArgList &variables, const char *opts="", const char *commonPath="", const char *indexCatName=nullptr)
Read data from a text file and create a dataset from it.
bool isWeighted() const override
Return true if dataset contains weighted events.
RooDirItem is a utility base class for RooFit objects that are to be attached to ROOT directories.
Definition: RooDirItem.h:22
virtual void Streamer(TBuffer &)
void removeFromDir(TObject *obj)
Remove object from directory it was added to.
Definition: RooDirItem.cxx:39
TDirectory * _dir
! Associated directory
Definition: RooDirItem.h:33
void appendToDir(TObject *obj, bool forceMemoryResident=false)
Append object to directory.
Definition: RooDirItem.cxx:51
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Definition: RooFormulaVar.h:30
A RooHist is a graphical representation of binned data based on the TGraphAsymmErrors class.
Definition: RooHist.h:29
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:38
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:67
RooLinkedListIterImpl begin() const
A RooPlot is a plot frame and a container for graphics objects within that frame.
Definition: RooPlot.h:43
RooAbsRealLValue * getPlotVar() const
Definition: RooPlot.h:137
void addPlotable(RooPlotable *plotable, Option_t *drawOptions="", bool invisible=false, bool refreshNorm=false)
Add the specified plotable object to our plot.
Definition: RooPlot.cxx:531
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:40
void setVal(double value) override
Set value of variable to 'value'.
Definition: RooRealVar.cxx:262
void setError(double value)
Definition: RooRealVar.h:64
double getErrorLo() const
Definition: RooRealVar.h:71
void removeAsymError()
Definition: RooRealVar.h:69
void setAsymError(double lo, double hi)
Definition: RooRealVar.h:70
double getErrorHi() const
Definition: RooRealVar.h:72
void removeError()
Definition: RooRealVar.h:65
static void activate()
Install atexit handler that calls CleanupRooFitAtExit() on program termination.
Definition: RooSentinel.cxx:54
A simple container to hold a batch of data values.
Definition: RooSpan.h:34
constexpr bool empty() const noexcept
Definition: RooSpan.h:124
The RooStringView is a wrapper around a C-syle string that can also be constructed from a std::string...
Definition: RooStringView.h:27
RooTreeDataStore is a TTree-backed data storage.
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...
RooVectorDataStore uses std::vectors to store data columns.
void append(RooAbsDataStore &other) override
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
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
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
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2968
virtual TList * GetList() const
Definition: TDirectory.h:222
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:4053
void Add(TObject *obj) override
Definition: TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition: TList.cxx:822
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
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
TClass * IsA() const override
Definition: TNamed.h:58
Mother of all ROOT objects.
Definition: TObject.h:41
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:525
Basic string class.
Definition: TString.h:136
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1171
virtual void Streamer(TBuffer &)
Stream a string object.
Definition: TString.cxx:1391
TString & Append(const char *cs)
Definition: TString.h:565
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:625
A TTree represents a columnar dataset.
Definition: TTree.h:79
TLine * line
RooCmdArg StoreAsymError(const RooArgSet &aset)
RooCmdArg StoreError(const RooArgSet &aset)
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RVec< PromoteType< T > > abs(const RVec< T > &v)
Definition: RVec.hxx:1780
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
Definition: StringUtils.cxx:23
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition: Common.h:18
@ DataHandling
Definition: RooGlobalFunc.h:64
@ InputArguments
Definition: RooGlobalFunc.h:63
bool checkIfRangesOverlap(RooArgSet const &observables, std::vector< std::string > const &rangeNames)
Check if there is any overlap when a list of ranges is applied to a set of observables.
Definition: RooHelpers.cxx:188
static constexpr double pc
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
Definition: Functions.h:282
void variables(TString dataset, TString fin="TMVA.root", TString dirName="InputVariables_Id", TString title="TMVA Input Variables", Bool_t isRegression=kFALSE, Bool_t useTMVAStyle=kTRUE)
Definition: file.py:1
Definition: first.py:1
Definition: graph.py:1
TLine l
Definition: textangle.C:4