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