Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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), 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), 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 std::unique_ptr<RooAbsArg> ret{_dstore->addColumn(var,adjustRange)};
1303 RooAbsArg* retPtr = ret.get();
1304 _vars.addOwned(std::move(ret));
1306 return retPtr;
1307}
1308
1309
1310////////////////////////////////////////////////////////////////////////////////
1311/// Add a column with the values of the given list of (function)
1312/// argument to this dataset. Each function value is calculated for
1313/// each event using the observable values of the event in case the
1314/// function depends on variables with names that are identical to
1315/// the observable names in the dataset
1316
1318{
1319 auto * holderSet = new RooArgSet{};
1320 for(RooAbsArg * var : varList) {
1321 holderSet->add(*addColumn(*var));
1322 }
1323 return holderSet;
1324}
1325
1326
1327
1328
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Special plot method for 'X-Y' datasets used in \f$ \chi^2 \f$ fitting.
1332/// For general plotting, see RooAbsData::plotOn().
1333///
1334/// These datasets
1335/// have one observable (X) and have weights (Y) and associated errors.
1336/// <table>
1337/// <tr><th> Contents options <th> Effect
1338/// <tr><td> YVar(RooRealVar& var) <td> Designate specified observable as 'y' variable
1339/// If not specified, the event weight will be the y variable
1340/// <tr><th> Histogram drawing options <th> Effect
1341/// <tr><td> DrawOption(const char* opt) <td> Select ROOT draw option for resulting TGraph object
1342/// <tr><td> LineStyle(Int_t style) <td> Select line style by ROOT line style code, default is solid
1343/// <tr><td> LineColor(Int_t color) <td> Select line color by ROOT color code, default is black
1344/// <tr><td> LineWidth(Int_t width) <td> Select line with in pixels, default is 3
1345/// <tr><td> MarkerStyle(Int_t style) <td> Select the ROOT marker style, default is 21
1346/// <tr><td> MarkerColor(Int_t color) <td> Select the ROOT marker color, default is black
1347/// <tr><td> MarkerSize(double size) <td> Select the ROOT marker size
1348/// <tr><td> Rescale(double factor) <td> Apply global rescaling factor to histogram
1349/// <tr><th> Misc. other options <th> Effect
1350/// <tr><td> Name(const chat* name) <td> Give curve specified name in frame. Useful if curve is to be referenced later
1351/// <tr><td> Invisible(bool flag) <td> Add curve to frame, but do not display. Useful in combination AddTo()
1352/// </table>
1353
1354RooPlot* RooDataSet::plotOnXY(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
1355 const RooCmdArg& arg3, const RooCmdArg& arg4,
1356 const RooCmdArg& arg5, const RooCmdArg& arg6,
1357 const RooCmdArg& arg7, const RooCmdArg& arg8) const
1358{
1359 checkInit() ;
1360
1361 RooLinkedList argList ;
1362 argList.Add((TObject*)&arg1) ; argList.Add((TObject*)&arg2) ;
1363 argList.Add((TObject*)&arg3) ; argList.Add((TObject*)&arg4) ;
1364 argList.Add((TObject*)&arg5) ; argList.Add((TObject*)&arg6) ;
1365 argList.Add((TObject*)&arg7) ; argList.Add((TObject*)&arg8) ;
1366
1367 // Process named arguments
1368 RooCmdConfig pc(Form("RooDataSet::plotOnXY(%s)",GetName())) ;
1369 pc.defineString("drawOption","DrawOption",0,"P") ;
1370 pc.defineString("histName","Name",0,"") ;
1371 pc.defineInt("lineColor","LineColor",0,-999) ;
1372 pc.defineInt("lineStyle","LineStyle",0,-999) ;
1373 pc.defineInt("lineWidth","LineWidth",0,-999) ;
1374 pc.defineInt("markerColor","MarkerColor",0,-999) ;
1375 pc.defineInt("markerStyle","MarkerStyle",0,8) ;
1376 pc.defineDouble("markerSize","MarkerSize",0,-999) ;
1377 pc.defineInt("fillColor","FillColor",0,-999) ;
1378 pc.defineInt("fillStyle","FillStyle",0,-999) ;
1379 pc.defineInt("histInvisible","Invisible",0,0) ;
1380 pc.defineDouble("scaleFactor","Rescale",0,1.) ;
1381 pc.defineObject("xvar","XVar",0,0) ;
1382 pc.defineObject("yvar","YVar",0,0) ;
1383
1384
1385 // Process & check varargs
1386 pc.process(argList) ;
1387 if (!pc.ok(true)) {
1388 return frame ;
1389 }
1390
1391 // Extract values from named arguments
1392 const char* drawOptions = pc.getString("drawOption") ;
1393 Int_t histInvisible = pc.getInt("histInvisible") ;
1394 const char* histName = pc.getString("histName",0,true) ;
1395 double scaleFactor = pc.getDouble("scaleFactor") ;
1396
1397 RooRealVar* xvar = (RooRealVar*) _vars.find(frame->getPlotVar()->GetName()) ;
1398
1399 // Determine Y variable (default is weight, if present)
1400 RooRealVar* yvar = (RooRealVar*)(pc.getObject("yvar")) ;
1401
1402 // Sanity check. XY plotting only applies to weighted datasets if no YVar is specified
1403 if (!_wgtVar && !yvar) {
1404 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR: no YVar() argument specified and dataset is not weighted" << endl ;
1405 return 0 ;
1406 }
1407
1408 RooRealVar* dataY = yvar ? (RooRealVar*) _vars.find(yvar->GetName()) : 0 ;
1409 if (yvar && !dataY) {
1410 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR on YVar() argument, dataset does not contain a variable named " << yvar->GetName() << endl ;
1411 return 0 ;
1412 }
1413
1414
1415 // Make RooHist representing XY contents of data
1416 RooHist* graph = new RooHist ;
1417 if (histName) {
1418 graph->SetName(histName) ;
1419 } else {
1420 graph->SetName(Form("hxy_%s",GetName())) ;
1421 }
1422
1423 for (int i=0 ; i<numEntries() ; i++) {
1424 get(i) ;
1425 double x = xvar->getVal() ;
1426 double exlo = xvar->getErrorLo() ;
1427 double exhi = xvar->getErrorHi() ;
1428 double y,eylo,eyhi ;
1429 if (!dataY) {
1430 y = weight() ;
1431 weightError(eylo,eyhi) ;
1432 } else {
1433 y = dataY->getVal() ;
1434 eylo = dataY->getErrorLo() ;
1435 eyhi = dataY->getErrorHi() ;
1436 }
1437 graph->addBinWithXYError(x,y,-1*exlo,exhi,-1*eylo,eyhi,scaleFactor) ;
1438 }
1439
1440 // Adjust style options according to named arguments
1441 Int_t lineColor = pc.getInt("lineColor") ;
1442 Int_t lineStyle = pc.getInt("lineStyle") ;
1443 Int_t lineWidth = pc.getInt("lineWidth") ;
1444 Int_t markerColor = pc.getInt("markerColor") ;
1445 Int_t markerStyle = pc.getInt("markerStyle") ;
1446 Size_t markerSize = pc.getDouble("markerSize") ;
1447 Int_t fillColor = pc.getInt("fillColor") ;
1448 Int_t fillStyle = pc.getInt("fillStyle") ;
1449
1450 if (lineColor!=-999) graph->SetLineColor(lineColor) ;
1451 if (lineStyle!=-999) graph->SetLineStyle(lineStyle) ;
1452 if (lineWidth!=-999) graph->SetLineWidth(lineWidth) ;
1453 if (markerColor!=-999) graph->SetMarkerColor(markerColor) ;
1454 if (markerStyle!=-999) graph->SetMarkerStyle(markerStyle) ;
1455 if (markerSize!=-999) graph->SetMarkerSize(markerSize) ;
1456 if (fillColor!=-999) graph->SetFillColor(fillColor) ;
1457 if (fillStyle!=-999) graph->SetFillStyle(fillStyle) ;
1458
1459 // Add graph to frame
1460 frame->addPlotable(graph,drawOptions,histInvisible) ;
1461
1462 return frame ;
1463}
1464
1465
1466
1467
1468////////////////////////////////////////////////////////////////////////////////
1469/// Read given list of ascii files, and construct a data set, using the given
1470/// ArgList as structure definition.
1471/// \param fileList Multiple file names, comma separated. Each
1472/// file is optionally prefixed with 'commonPath' if such a path is
1473/// provided
1474///
1475/// \param varList Specify the dimensions of the dataset to be built.
1476/// This list describes the order in which these dimensions appear in the
1477/// ascii files to be read.
1478/// Each line in the ascii file should contain N white-space separated
1479/// tokens, with N the number of args in `varList`. Any text beyond
1480/// N tokens will be ignored with a warning message.
1481/// (NB: This is the default output of RooArgList::writeToStream())
1482///
1483/// \param verbOpt `Q` be quiet, `D` debug mode (verbose)
1484///
1485/// \param commonPath All filenames in `fileList` will be prefixed with this optional path.
1486///
1487/// \param indexCatName Interpret the data as belonging to category `indexCatName`.
1488/// When multiple files are read, a RooCategory arg in `varList` can
1489/// optionally be designated to hold information about the source file
1490/// of each data point. This feature is enabled by giving the name
1491/// of the (already existing) category variable in `indexCatName`.
1492///
1493/// \attention If the value of any of the variables on a given line exceeds the
1494/// fit range associated with that dimension, the entire line will be
1495/// ignored. A warning message is printed in each case, unless the
1496/// `Q` verbose option is given. The number of events read and skipped
1497/// is always summarized at the end.
1498///
1499/// If no further information is given a label name 'fileNNN' will
1500/// be assigned to each event, where NNN is the sequential number of
1501/// the source file in `fileList`.
1502///
1503/// Alternatively, it is possible to override the default label names
1504/// of the index category by specifying them in the fileList string:
1505/// When instead of `file1.txt,file2.txt` the string
1506/// `file1.txt:FOO,file2.txt:BAR` is specified, a state named "FOO"
1507/// is assigned to the index category for each event originating from
1508/// file1.txt. The labels FOO,BAR may be predefined in the index
1509/// category via defineType(), but don't have to be.
1510///
1511/// Finally, one can also assign the same label to multiple files,
1512/// either by specifying `file1.txt:FOO,file2,txt:FOO,file3.txt:BAR`
1513/// or `file1.txt,file2.txt:FOO,file3.txt:BAR`.
1514///
1515
1516RooDataSet *RooDataSet::read(const char *fileList, const RooArgList &varList,
1517 const char *verbOpt, const char* commonPath,
1518 const char* indexCatName) {
1519 // Make working copy of variables list
1520 RooArgList variables(varList) ;
1521
1522 // Append blinding state category to variable list if not already there
1523 bool ownIsBlind(true) ;
1524 RooAbsArg* blindState = variables.find("blindState") ;
1525 if (!blindState) {
1526 blindState = new RooCategory("blindState","Blinding State") ;
1527 variables.add(*blindState) ;
1528 } else {
1529 ownIsBlind = false ;
1530 if (blindState->IsA()!=RooCategory::Class()) {
1531 oocoutE(nullptr,DataHandling) << "RooDataSet::read: ERROR: variable list already contains"
1532 << "a non-RooCategory blindState member" << endl ;
1533 return 0 ;
1534 }
1535 oocoutW(nullptr,DataHandling) << "RooDataSet::read: WARNING: recycling existing "
1536 << "blindState category in variable list" << endl ;
1537 }
1538 RooCategory* blindCat = (RooCategory*) blindState ;
1539
1540 // Configure blinding state category
1541 blindCat->setAttribute("Dynamic") ;
1542 blindCat->defineType("Normal",0) ;
1543 blindCat->defineType("Blind",1) ;
1544
1545 // parse the option string
1546 TString opts= verbOpt;
1547 opts.ToLower();
1548 bool verbose= !opts.Contains("q");
1549 bool debug= opts.Contains("d");
1550
1551 auto data = std::make_unique<RooDataSet>("dataset", fileList, variables);
1552 if (ownIsBlind) { variables.remove(*blindState) ; delete blindState ; }
1553 if(!data) {
1554 oocoutE(nullptr,DataHandling) << "RooDataSet::read: unable to create a new dataset"
1555 << endl;
1556 return nullptr;
1557 }
1558
1559 // Redirect blindCat to point to the copy stored in the data set
1560 blindCat = (RooCategory*) data->_vars.find("blindState") ;
1561
1562 // Find index category, if requested
1563 RooCategory *indexCat = 0;
1564 //RooCategory *indexCatOrig = 0;
1565 if (indexCatName) {
1566 RooAbsArg* tmp = 0;
1567 tmp = data->_vars.find(indexCatName) ;
1568 if (!tmp) {
1569 oocoutE(data.get(),DataHandling) << "RooDataSet::read: no index category named "
1570 << indexCatName << " in supplied variable list" << endl ;
1571 return nullptr;
1572 }
1573 if (tmp->IsA()!=RooCategory::Class()) {
1574 oocoutE(data.get(),DataHandling) << "RooDataSet::read: variable " << indexCatName
1575 << " is not a RooCategory" << endl ;
1576 return nullptr;
1577 }
1578 indexCat = static_cast<RooCategory*>(tmp);
1579
1580 // Prevent RooArgSet from attempting to read in indexCat
1581 indexCat->setAttribute("Dynamic") ;
1582 }
1583
1584
1585 Int_t outOfRange(0) ;
1586
1587 // Loop over all names in comma separated list
1588 Int_t fileSeqNum(0);
1589 for (const auto& filename : ROOT::Split(std::string(fileList), ", ")) {
1590 // Determine index category number, if this option is active
1591 if (indexCat) {
1592
1593 // Find and detach optional file category name
1594 const char *catname = strchr(filename.c_str(),':');
1595
1596 if (catname) {
1597 // Use user category name if provided
1598 catname++ ;
1599
1600 if (indexCat->hasLabel(catname)) {
1601 // Use existing category index
1602 indexCat->setLabel(catname);
1603 } else {
1604 // Register cat name
1605 indexCat->defineType(catname,fileSeqNum) ;
1606 indexCat->setIndex(fileSeqNum) ;
1607 }
1608 } else {
1609 // Assign autogenerated name
1610 char newLabel[128] ;
1611 snprintf(newLabel,128,"file%03d",fileSeqNum) ;
1612 if (indexCat->defineType(newLabel,fileSeqNum)) {
1613 oocoutE(data.get(), DataHandling) << "RooDataSet::read: Error, cannot register automatic type name " << newLabel
1614 << " in index category " << indexCat->GetName() << endl ;
1615 return 0 ;
1616 }
1617 // Assign new category number
1618 indexCat->setIndex(fileSeqNum) ;
1619 }
1620 }
1621
1622 oocoutI(data.get(), DataHandling) << "RooDataSet::read: reading file " << filename << endl ;
1623
1624 // Prefix common path
1625 TString fullName(commonPath) ;
1626 fullName.Append(filename) ;
1627 ifstream file(fullName) ;
1628
1629 if (!file.good()) {
1630 oocoutE(data.get(), DataHandling) << "RooDataSet::read: unable to open '"
1631 << filename << "'. Returning nullptr now." << endl;
1632 return nullptr;
1633 }
1634
1635 // double value;
1636 Int_t line(0) ;
1637 bool haveBlindString(false) ;
1638
1639 while(file.good() && !file.eof()) {
1640 line++;
1641 if(debug) oocxcoutD(data.get(),DataHandling) << "reading line " << line << endl;
1642
1643 // process comment lines
1644 if (file.peek() == '#') {
1645 if(debug) oocxcoutD(data.get(),DataHandling) << "skipping comment on line " << line << endl;
1646 } else {
1647 // Read single line
1648 bool readError = variables.readFromStream(file,true,verbose) ;
1649 data->_vars.assign(variables) ;
1650
1651 // Stop on read error
1652 if(!file.good()) {
1653 oocoutE(data.get(), DataHandling) << "RooDataSet::read(static): read error at line " << line << endl ;
1654 break;
1655 }
1656
1657 if (readError) {
1658 outOfRange++ ;
1659 } else {
1660 blindCat->setIndex(haveBlindString) ;
1661 data->fill(); // store this event
1662 }
1663 }
1664
1665 // Skip all white space (including empty lines).
1666 while (isspace(file.peek())) {
1667 char dummy;
1668 file >> std::noskipws >> dummy >> std::skipws;
1669 }
1670 }
1671
1672 file.close();
1673
1674 // get next file name
1675 fileSeqNum++ ;
1676 }
1677
1678 if (indexCat) {
1679 // Copy dynamically defined types from new data set to indexCat in original list
1680 assert(dynamic_cast<RooCategory*>(variables.find(indexCatName)));
1681 const auto origIndexCat = static_cast<RooCategory*>(variables.find(indexCatName));
1682 for (const auto& nameIdx : *indexCat) {
1683 origIndexCat->defineType(nameIdx.first, nameIdx.second);
1684 }
1685 }
1686 oocoutI(data.get(),DataHandling) << "RooDataSet::read: read " << data->numEntries()
1687 << " events (ignored " << outOfRange << " out of range events)" << endl;
1688
1689 return data.release();
1690}
1691
1692
1693
1694
1695////////////////////////////////////////////////////////////////////////////////
1696/// Write the contents of this dataset to an ASCII file with the specified name.
1697/// Each event will be written as a single line containing the written values
1698/// of each observable in the order they were declared in the dataset and
1699/// separated by whitespaces
1700
1701bool RooDataSet::write(const char* filename) const
1702{
1703 // Open file for writing
1704 ofstream ofs(filename) ;
1705 if (ofs.fail()) {
1706 coutE(DataHandling) << "RooDataSet::write(" << GetName() << ") cannot create file " << filename << endl ;
1707 return true ;
1708 }
1709
1710 // Write all lines as arglist in compact mode
1711 coutI(DataHandling) << "RooDataSet::write(" << GetName() << ") writing ASCII file " << filename << endl ;
1712 return write(ofs);
1713}
1714
1715////////////////////////////////////////////////////////////////////////////////
1716/// Write the contents of this dataset to the stream.
1717/// Each event will be written as a single line containing the written values
1718/// of each observable in the order they were declared in the dataset and
1719/// separated by whitespaces
1720
1721bool RooDataSet::write(ostream & ofs) const {
1722 checkInit();
1723
1724 for (Int_t i=0; i<numEntries(); ++i) {
1725 get(i)->writeToStream(ofs,true);
1726 }
1727
1728 if (ofs.fail()) {
1729 coutW(DataHandling) << "RooDataSet::write(" << GetName() << "): WARNING error(s) have occured in writing" << endl ;
1730 }
1731
1732 return ofs.fail() ;
1733}
1734
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Print info about this dataset to the specified output stream.
1738///
1739/// Standard: number of entries
1740/// Shape: list of variables we define & were generated with
1741
1742void RooDataSet::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
1743{
1744 checkInit() ;
1745 RooAbsData::printMultiline(os,contents,verbose,indent) ;
1746 if (_wgtVar) {
1747 os << indent << " Dataset variable \"" << _wgtVar->GetName() << "\" is interpreted as the event weight" << endl ;
1748 }
1749}
1750
1751
1752////////////////////////////////////////////////////////////////////////////////
1753/// Print value of the dataset, i.e. the sum of weights contained in the dataset
1754
1755void RooDataSet::printValue(ostream& os) const
1756{
1757 os << numEntries() << " entries" ;
1758 if (isWeighted()) {
1759 os << " (" << sumEntries() << " weighted)" ;
1760 }
1761}
1762
1763
1764
1765////////////////////////////////////////////////////////////////////////////////
1766/// Print argument of dataset, i.e. the observable names
1767
1768void RooDataSet::printArgs(ostream& os) const
1769{
1770 os << "[" ;
1771 bool first(true) ;
1772 for(RooAbsArg* arg : _varsNoWgt) {
1773 if (first) {
1774 first=false ;
1775 } else {
1776 os << "," ;
1777 }
1778 os << arg->GetName() ;
1779 }
1780 if (_wgtVar) {
1781 os << ",weight:" << _wgtVar->GetName() ;
1782 }
1783 os << "]" ;
1784}
1785
1786
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Change the name of this dataset into the given name
1790
1791void RooDataSet::SetName(const char *name)
1792{
1793 if (_dir) _dir->GetList()->Remove(this);
1794 // We need to use the function from RooAbsData, because it already overrides TNamed::SetName
1796 if (_dir) _dir->GetList()->Add(this);
1797}
1798
1799
1800////////////////////////////////////////////////////////////////////////////////
1801/// Change the title of this dataset into the given name
1802
1803void RooDataSet::SetNameTitle(const char *name, const char* title)
1804{
1805 SetName(name);
1806 SetTitle(title);
1807}
1808
1809
1810////////////////////////////////////////////////////////////////////////////////
1811/// Stream an object of class RooDataSet.
1812
1814{
1815 if (R__b.IsReading()) {
1816
1817 UInt_t R__s, R__c;
1818 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1819
1820 if (R__v>1) {
1821
1822 // Use new-style streaming for version >1
1823 R__b.ReadClassBuffer(RooDataSet::Class(),this,R__v,R__s,R__c);
1824
1825 } else {
1826
1827 // Legacy dataset conversion happens here. Legacy RooDataSet inherits from RooTreeData
1828 // which in turn inherits from RooAbsData. Manually stream RooTreeData contents on
1829 // file here and convert it into a RooTreeDataStore which is installed in the
1830 // new-style RooAbsData base class
1831
1832 // --- This is the contents of the streamer code of RooTreeData version 1 ---
1833 UInt_t R__s1, R__c1;
1834 Version_t R__v1 = R__b.ReadVersion(&R__s1, &R__c1); if (R__v1) { }
1835
1837 TTree* X_tree(0) ; R__b >> X_tree;
1838 RooArgSet X_truth ; X_truth.Streamer(R__b);
1839 TString X_blindString ; X_blindString.Streamer(R__b);
1840 R__b.CheckByteCount(R__s1, R__c1, TClass::GetClass("RooTreeData"));
1841 // --- End of RooTreeData-v1 streamer
1842
1843 // Construct RooTreeDataStore from X_tree and complete initialization of new-style RooAbsData
1844 _dstore = std::make_unique<RooTreeDataStore>(X_tree,_vars) ;
1845 _dstore->SetName(GetName()) ;
1846 _dstore->SetTitle(GetTitle()) ;
1847 _dstore->checkInit() ;
1848
1849 // This is the contents of the streamer code of RooDataSet version 1
1851 _varsNoWgt.Streamer(R__b);
1852 R__b >> _wgtVar;
1853 R__b.CheckByteCount(R__s, R__c, RooDataSet::IsA());
1854
1855
1856 }
1857 } else {
1859 }
1860}
1861
1862
1863
1864////////////////////////////////////////////////////////////////////////////////
1865/// Convert vector-based storage to tree-based storage. This implementation overrides the base class
1866/// implementation because the latter doesn't transfer weights.
1868{
1870 _dstore = std::make_unique<RooTreeDataStore>(GetName(), GetTitle(), _vars, *_dstore, nullptr, _wgtVar ? _wgtVar->GetName() : nullptr);
1872 }
1873}
1874
1875
1876namespace {
1877
1878 // Compile-time test if we can still use TStrings for the constructors of
1879 // RooDataClasses, either for both name and title or for only one of them.
1880 TString tstr = "tstr";
1881 const char * cstr = "cstr";
1882 RooRealVar x{"x", "x", 1.0};
1883 RooArgSet vars{x};
1884 RooDataSet d1(tstr, tstr, vars);
1885 RooDataSet d2(tstr, cstr, vars);
1886 RooDataSet d3(cstr, tstr, vars);
1887
1888} // namespace
1889
1890
1891void RooDataSet::loadValuesFromSlices(RooCategory &indexCat, std::map<std::string, RooAbsData *> const &slices,
1892 const char *rangeName, RooFormulaVar const *cutVar, const char *cutSpec)
1893{
1894
1895 if (cutVar && cutSpec) {
1896 throw std::invalid_argument("Only one of cutVar or cutSpec should be not a nullptr!");
1897 }
1898
1899 auto &indexCatInData = *static_cast<RooCategory *>(_vars.find(indexCat.GetName()));
1900
1901 for (auto const &item : slices) {
1902 std::unique_ptr<RooDataSet> sliceDataSet;
1903 RooAbsData* sliceData = item.second;
1904
1905 // If we are importing a RooDataHist, first convert it to a RooDataSet
1906 if(sliceData->InheritsFrom(RooDataHist::Class())) {
1907 sliceDataSet = makeDataSetFromDataHist(static_cast<RooDataHist const &>(*sliceData));
1908 sliceData = sliceDataSet.get();
1909 }
1910
1911 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
1912 if (!indexCat.hasLabel(item.first)) {
1913 indexCat.defineType(item.first);
1914 coutI(InputArguments) << "RooDataSet::ctor(" << GetName() << ") defining state \"" << item.first
1915 << "\" in index category " << indexCat.GetName() << std::endl;
1916 }
1917 if (!indexCatInData.hasLabel(item.first)) {
1918 indexCatInData.defineType(item.first);
1919 }
1920 indexCatInData.setLabel(item.first.c_str());
1921 std::unique_ptr<RooFormulaVar> cutVarTmp;
1922 if (cutSpec) {
1923 cutVarTmp = std::make_unique<RooFormulaVar>(cutSpec, cutSpec, *sliceData->get());
1924 cutVar = cutVarTmp.get();
1925 }
1926 _dstore->loadValues(sliceData->store(), cutVar, rangeName);
1927 }
1928}
#define e(i)
Definition RSha256.hxx:103
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
#define coutI(a)
#define ccoutE(a)
#define oocoutW(o, a)
#define oocxcoutD(o, a)
#define coutW(a)
#define oocoutE(o, a)
#define oocoutI(o, a)
#define coutE(a)
#define TRACE_DESTROY
Definition RooTrace.h:24
#define TRACE_CREATE
Definition RooTrace.h:23
int Int_t
Definition RtypesCore.h:45
float Size_t
Definition RtypesCore.h:96
short Version_t
Definition RtypesCore.h:65
#define ClassImp(name)
Definition Rtypes.h:377
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
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2467
#define snprintf
Definition civetweb.c:1540
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Definition Util.h:122
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:74
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
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.
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 RooAbsDataStore * merge(const RooArgSet &allvars, std::list< RooAbsDataStore * > dstoreList)=0
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:59
virtual const RooArgSet * get() const
Definition RooAbsData.h:103
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Interface for detailed printing of object.
void SetName(const char *name) override
Set the name of the TNamed.
RooAbsDataStore * store()
Definition RooAbsData.h:79
void checkInit() const
static StorageType defaultStorageType
Definition RooAbsData.h:325
std::unique_ptr< RooAbsDataStore > _dstore
Data storage implementation.
Definition RooAbsData.h:364
virtual void fill()
RooArgSet _vars
Dimensions of this data set.
Definition RooAbsData.h:361
RooArgSet _cachedVars
! External variables cached with this data set
Definition RooAbsData.h:362
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
StorageType storageType
Definition RooAbsData.h:327
virtual bool isWeighted() const
Definition RooAbsData.h:154
void Streamer(TBuffer &) override
Stream an object of class RooAbsData.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:91
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:55
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.
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.
bool defineObject(const char *name, const char *argName, Int_t setNum, const TObject *obj=nullptr, bool isArray=false)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
double getDouble(const char *name, double defaultValue=0.0)
Return double property registered with name 'name'.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
Int_t getInt(const char *name, Int_t defaultValue=0)
Return integer property registered with name 'name'.
bool defineInt(const char *name, const char *argName, Int_t intNum, Int_t defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
bool defineString(const char *name, const char *argName, Int_t stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
bool ok(bool verbose) const
Return true of parsing was successful.
TObject * getObject(const char *name, TObject *obj=nullptr)
Return TObject property registered with name 'name'.
const char * getString(const char *name, const char *defaultValue="", bool convEmptyToNull=false)
Return string property registered with name 'name'.
bool defineDouble(const char *name, const char *argName, Int_t doubleNum, double defValue=0.0)
Define double property name 'name' mapped to double in slot 'doubleNum' in RooCmdArg with name argNam...
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.
double weightSquared(std::size_t i) const
Return squared weight sum of i-th bin.
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
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.
RooRealVar * _wgtVar
Pointer to weight variable (if set)
Definition RooDataSet.h:173
bool _doWeightErrorCheck
! When adding events with weights, check that weights can actually be stored.
Definition RooDataSet.h:185
static void cleanup()
RooArgSet _varsNoWgt
Vars without weight variable.
Definition RooDataSet.h:172
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.
const RooArgSet * get() const override
Return a RooArgSet with the coordinates of the current event.
void add(const RooArgSet &row, double weight=1.0, double weightError=0.0) override
Add one ore more rows of data.
void initialize(const char *wgtVarName)
Initialize the dataset.
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:189
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.
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.
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.
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.
std::unique_ptr< std::vector< double > > _sumW2Buffer
! Buffer for sumW2 in case a batch of values is requested.
Definition RooDataSet.h:187
void Streamer(TBuffer &) override
Stream an object of class RooDataSet.
unsigned short _errorMsgCount
! Counter to silence error messages when filling dataset.
Definition RooDataSet.h:184
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.
double weightSquared() const override
Return squared event weight of the current event.
double weight() const override
Return event weight of current event.
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.
TDirectory * _dir
! Associated directory
Definition RooDirItem.h:33
void appendToDir(TObject *obj, bool forceMemoryResident=false)
Append object to directory.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
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 ...
virtual void Add(TObject *arg)
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:528
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'.
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.
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...
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:139
void ToLower()
Change string to lower-case.
Definition TString.cxx:1170
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1390
TString & Append(const char *cs)
Definition TString.h:576
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
A TTree represents a columnar dataset.
Definition TTree.h:79
TLine * line
RooCmdArg StoreError(const RooArgSet &aset)
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition Common.h:18
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.
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
Definition Functions.h:282
Definition file.py:1
Definition first.py:1
Definition graph.py:1
TLine l
Definition textangle.C:4
#define Split(a, ahi, alo)
Definition triangle.c:4776