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 "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 namespace std;
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 = (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{static_cast<RooArgSet*>(_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{static_cast<RooArgSet*>(_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());
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);
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::Detail::owningPtr(std::make_unique<RooDataSet>(newName, newTitle, vars2, WeightVar(wgtVarName), StoreError(errorSet), StoreAsymError(asymErrorSet)));
783}
784
785
786
787////////////////////////////////////////////////////////////////////////////////
788/// Initialize the dataset. If wgtVarName is not null, interpret the observable
789/// with that name as event weight
790
791void RooDataSet::initialize(const char* wgtVarName)
792{
795 _wgtVar = nullptr ;
796 if (wgtVarName) {
797 RooAbsArg* wgt = _varsNoWgt.find(wgtVarName) ;
798 if (!wgt) {
799 coutE(DataHandling) << "RooDataSet::RooDataSet(" << GetName() << "): designated weight variable "
800 << wgtVarName << " not found in set of variables, no weighting will be assigned" << endl ;
801 throw std::invalid_argument("RooDataSet::initialize() weight variable could not be initialised.");
802 } else if (!dynamic_cast<RooRealVar*>(wgt)) {
803 coutE(DataHandling) << "RooDataSet::RooDataSet(" << GetName() << "): designated weight variable "
804 << wgtVarName << " is not of type RooRealVar, no weighting will be assigned" << endl ;
805 throw std::invalid_argument("RooDataSet::initialize() weight variable could not be initialised.");
806 } else {
807 _varsNoWgt.remove(*wgt) ;
808 _wgtVar = (RooRealVar*) wgt ;
809 }
810 }
811}
812
813
814
815////////////////////////////////////////////////////////////////////////////////
816/// Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods
817
818std::unique_ptr<RooAbsData> RooDataSet::reduceEng(const RooArgSet &varSubset, const RooFormulaVar *cutVar,
819 const char *cutRange, std::size_t nStart, std::size_t nStop)
820{
821 checkInit();
822 RooArgSet tmp(varSubset);
823 if (_wgtVar) {
824 tmp.add(*_wgtVar);
825 }
826
827 auto createEmptyClone = [&]() { return emptyClone(GetName(), GetTitle(), &tmp); };
828
829 std::unique_ptr<RooAbsData> out{createEmptyClone()};
830
831 if (!cutRange || strchr(cutRange, ',') == nullptr) {
832 auto &ds = static_cast<RooDataSet &>(*out);
833 ds._dstore = _dstore->reduce(ds.GetName(), ds.GetTitle(), ds._vars, cutVar, cutRange, nStart, nStop);
834 ds._cachedVars.add(_dstore->cachedVars());
835 } else {
836 // Composite case: multiple ranges
837 auto tokens = ROOT::Split(cutRange, ",");
838 if (RooHelpers::checkIfRangesOverlap(tmp, tokens)) {
839 std::stringstream errMsg;
840 errMsg << "Error in RooAbsData::reduce! The ranges " << cutRange << " are overlapping!";
841 throw std::runtime_error(errMsg.str());
842 }
843 for (const auto &token : tokens) {
844 std::unique_ptr<RooAbsData> appendedData{createEmptyClone()};
845 auto &ds = static_cast<RooDataSet &>(*appendedData);
846 ds._dstore = _dstore->reduce(ds.GetName(), ds.GetTitle(), ds._vars, cutVar, token.c_str(), nStart, nStop);
847 ds._cachedVars.add(_dstore->cachedVars());
848 static_cast<RooDataSet &>(*out).append(ds);
849 }
850 }
851 return out;
852}
853
854
855
856////////////////////////////////////////////////////////////////////////////////
857/// Destructor
858
860{
861 removeFromDir(this) ;
863}
864
865
866
867////////////////////////////////////////////////////////////////////////////////
868/// Return binned clone of this dataset
869
870RooFit::OwningPtr<RooDataHist> RooDataSet::binnedClone(const char* newName, const char* newTitle) const
871{
872 std::string title;
873 std::string name;
874 if (newName) {
875 name = newName ;
876 } else {
877 name = std::string(GetName()) + "_binned" ;
878 }
879 if (newTitle) {
880 title = newTitle ;
881 } else {
882 title = std::string(GetTitle()) + "_binned" ;
883 }
884
885 return RooFit::Detail::owningPtr(std::make_unique<RooDataHist>(name,title,*get(),*this));
886}
887
888
889
890////////////////////////////////////////////////////////////////////////////////
891/// Return event weight of current event
892
893double RooDataSet::weight() const
894{
895 return store()->weight() ;
896}
897
898
899
900////////////////////////////////////////////////////////////////////////////////
901/// Return squared event weight of the current event. If this RooDataSet has no
902/// weight errors set, this will be the same as `weight() * weight()`, like
903/// expected for an unbinned dataset. When weight errors are set, it is assumed
904/// that the RooDataSet represents a weighted binned dataset and
905/// weightSquared() is the corresponding sum of weight squares for the bin.
906
908{
909 const double w = store()->weight();
910 const double e = weightError();
911 return e > 0.0 ? e * e : w * w;
912}
913
914
915////////////////////////////////////////////////////////////////////////////////
916/// \see RooAbsData::getWeightBatch().
917std::span<const double> RooDataSet::getWeightBatch(std::size_t first, std::size_t len, bool sumW2 /*=false*/) const {
918
919 std::size_t nEntries = this->numEntries(); // for the casting to std::size_t
920
921 if(first >= nEntries || (first + len) > nEntries) {
922 throw std::runtime_error("RooDataSet::getWeightBatch(): requested range not valid for dataset.");
923 }
924
925 std::span<const double> allWeights = _dstore->getWeightBatch(0, numEntries());
926 if(allWeights.empty()) return {};
927
928 if(!sumW2) return {&*(std::cbegin(allWeights) + first), len};
929
930 // Treat the sumW2 case with a result buffer, first reset buffer if the
931 // number of entries doesn't match with the dataset anymore
932 if(_sumW2Buffer && _sumW2Buffer->size() != nEntries) _sumW2Buffer.reset();
933
934 if (!_sumW2Buffer) {
935 _sumW2Buffer = std::make_unique<std::vector<double>>();
936 _sumW2Buffer->reserve(nEntries);
937
938 for (std::size_t i = 0; i < nEntries; ++i) {
939 get(i);
940 _sumW2Buffer->push_back(weightSquared());
941 }
942 }
943
944 return std::span<const double>(&*(_sumW2Buffer->begin() + first), len);
945}
946
947
948////////////////////////////////////////////////////////////////////////////////
949/// \copydoc RooAbsData::weightError(double&,double&,RooAbsData::ErrorType) const
950/// \param etype error type
951void RooDataSet::weightError(double& lo, double& hi, ErrorType etype) const
952{
953 store()->weightError(lo,hi,etype) ;
954}
955
956
957////////////////////////////////////////////////////////////////////////////////
958/// \copydoc RooAbsData::weightError(ErrorType)
959/// \param etype error type
961{
962 return store()->weightError(etype) ;
963}
964
965
966////////////////////////////////////////////////////////////////////////////////
967/// Return RooArgSet with coordinates of event 'index'
968
970{
971 const RooArgSet* ret = RooAbsData::get(index) ;
972 return ret ? &_varsNoWgt : nullptr ;
973}
974
975
976////////////////////////////////////////////////////////////////////////////////
977
979{
980 return store()->sumEntries() ;
981}
982
983
984////////////////////////////////////////////////////////////////////////////////
985/// Return the sum of weights in all entries matching cutSpec (if specified)
986/// and in named range cutRange (if specified)
987
988double RooDataSet::sumEntries(const char* cutSpec, const char* cutRange) const
989{
990 // Setup RooFormulaVar for cutSpec if it is present
991 std::unique_ptr<RooFormula> select = nullptr ;
992 if (cutSpec && strlen(cutSpec) > 0) {
993 select = std::make_unique<RooFormula>("select",cutSpec,*get()) ;
994 }
995
996 // Shortcut for unweighted unselected datasets
997 if (!select && !cutRange && !isWeighted()) {
998 return numEntries() ;
999 }
1000
1001 // Otherwise sum the weights in the event
1003 for (int i = 0 ; i<numEntries() ; i++) {
1004 get(i) ;
1005 if (select && select->eval()==0.) continue ;
1006 if (cutRange && !_vars.allInRange(cutRange)) continue ;
1007 sumw += weight();
1008 }
1009
1010 return sumw.Sum() ;
1011}
1012
1013
1014
1015
1016////////////////////////////////////////////////////////////////////////////////
1017/// Return true if dataset contains weighted events
1018
1020{
1021 return store() ? store()->isWeighted() : false;
1022}
1023
1024
1025
1026////////////////////////////////////////////////////////////////////////////////
1027/// Returns true if histogram contains bins with entries with a non-integer weight
1028
1030{
1031 // Return false if we have no weights
1032 if (!_wgtVar) return false ;
1033
1034 // Now examine individual weights
1035 for (int i=0 ; i<numEntries() ; i++) {
1036 get(i) ;
1037 if (std::abs(weight()-Int_t(weight()))>1e-10) return true ;
1038 }
1039 // If sum of weights is less than number of events there are negative (integer) weights
1040 if (sumEntries()<numEntries()) return true ;
1041
1042 return false ;
1043}
1044
1045
1046
1047
1048////////////////////////////////////////////////////////////////////////////////
1049/// Return a RooArgSet with the coordinates of the current event
1050
1052{
1053 return &_varsNoWgt ;
1054}
1055
1056
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1060/// Any variables present in 'data' but not in the dataset will be silently ignored.
1061/// \param[in] data Data point.
1062/// \param[in] wgt Event weight. Defaults to 1. The current value of the weight variable is
1063/// ignored.
1064/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1065/// \param[in] wgtError Optional weight error.
1066/// \note This requires including the weight variable in the set of `StoreError` variables when constructing
1067/// the dataset.
1068
1069void RooDataSet::add(const RooArgSet& data, double wgt, double wgtError)
1070{
1071 checkInit() ;
1072
1073 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1074
1076
1077 if (_wgtVar) {
1078 _wgtVar->setVal(wgt) ;
1079 if (wgtError!=0.) {
1080 _wgtVar->setError(wgtError) ;
1081 }
1082 } else if ((wgt != 1. || wgtError != 0.) && _errorMsgCount < 5) {
1083 ccoutE(DataHandling) << "An event weight/error was passed but no weight variable was defined"
1084 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1086 }
1087
1089 && wgtError != 0.
1090 && std::abs(wgt*wgt - wgtError)/wgtError > 1.E-15 //Exception for standard wgt^2 errors, which need not be stored.
1091 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreError")) {
1092 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1093 << "', but the weight variable '" << _wgtVar->GetName()
1094 << "' does not store errors. Check `StoreError` in the RooDataSet constructor." << std::endl;
1096 }
1097
1098 fill();
1099
1100 // Restore weight state
1101 if (_wgtVar) {
1102 _wgtVar->setVal(oldW);
1104 }
1105}
1106
1107
1108
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1112/// Any variables present in 'data' but not in the dataset will be silently ignored.
1113/// \param[in] indata Data point.
1114/// \param[in] inweight Event weight. The current value of the weight variable is ignored.
1115/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1116/// \param[in] weightErrorLo Asymmetric weight error.
1117/// \param[in] weightErrorHi Asymmetric weight error.
1118/// \note This requires including the weight variable in the set of `StoreAsymError` variables when constructing
1119/// the dataset.
1120
1121void RooDataSet::add(const RooArgSet& indata, double inweight, double weightErrorLo, double weightErrorHi)
1122{
1123 checkInit() ;
1124
1125 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1126
1127 _varsNoWgt.assign(indata);
1128 if (_wgtVar) {
1129 _wgtVar->setVal(inweight) ;
1130 _wgtVar->setAsymError(weightErrorLo,weightErrorHi) ;
1131 } else if (inweight != 1. && _errorMsgCount < 5) {
1132 ccoutE(DataHandling) << "An event weight was given but no weight variable was defined"
1133 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1135 }
1136
1138 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreAsymError")) {
1139 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1140 << "', but the weight variable '" << _wgtVar->GetName()
1141 << "' does not store errors. Check `StoreAsymError` in the RooDataSet constructor." << std::endl;
1143 }
1144
1145 fill();
1146
1147 // Restore weight state
1148 if (_wgtVar) {
1149 _wgtVar->setVal(oldW);
1151 }
1152}
1153
1154
1155
1156
1157
1158////////////////////////////////////////////////////////////////////////////////
1159/// Add a data point, with its coordinates specified in the 'data' argset, to the data set.
1160/// \attention The order and type of the input variables are **assumed** to be the same as
1161/// for the RooArgSet returned by RooDataSet::get(). Input values will just be written
1162/// into the internal data columns by ordinal position.
1163/// \param[in] data Data point.
1164/// \param[in] wgt Event weight. Defaults to 1. The current value of the weight variable is
1165/// ignored.
1166/// \note To obtain weighted events, a variable must be designated `WeightVar` in the constructor.
1167/// \param[in] wgtError Optional weight error.
1168/// \note This requires including the weight variable in the set of `StoreError` variables when constructing
1169/// the dataset.
1170
1171void RooDataSet::addFast(const RooArgSet& data, double wgt, double wgtError)
1172{
1173 checkInit() ;
1174
1175 const double oldW = _wgtVar ? _wgtVar->getVal() : 0.;
1176
1177 _varsNoWgt.assignFast(data,_dstore->dirtyProp());
1178 if (_wgtVar) {
1179 _wgtVar->setVal(wgt) ;
1180 if (wgtError!=0.) {
1181 _wgtVar->setError(wgtError) ;
1182 }
1183 } else if (wgt != 1. && _errorMsgCount < 5) {
1184 ccoutE(DataHandling) << "An event weight was given but no weight variable was defined"
1185 << " in the dataset '" << GetName() << "'. The weight will be ignored." << std::endl;
1187 }
1188
1189 fill();
1190
1192 && wgtError != 0. && wgtError != wgt*wgt //Exception for standard weight error, which need not be stored
1193 && _errorMsgCount < 5 && !_wgtVar->getAttribute("StoreError")) {
1194 coutE(DataHandling) << "An event weight error was passed to the RooDataSet '" << GetName()
1195 << "', but the weight variable '" << _wgtVar->GetName()
1196 << "' does not store errors. Check `StoreError` in the RooDataSet constructor." << std::endl;
1198 }
1200 _doWeightErrorCheck = false;
1201 }
1202
1203 if (_wgtVar) {
1204 _wgtVar->setVal(oldW);
1206 }
1207}
1208
1209
1210
1211////////////////////////////////////////////////////////////////////////////////
1212
1214 RooDataSet* data4, RooDataSet* data5, RooDataSet* data6)
1215{
1216 checkInit() ;
1217 list<RooDataSet*> dsetList ;
1218 if (data1) dsetList.push_back(data1) ;
1219 if (data2) dsetList.push_back(data2) ;
1220 if (data3) dsetList.push_back(data3) ;
1221 if (data4) dsetList.push_back(data4) ;
1222 if (data5) dsetList.push_back(data5) ;
1223 if (data6) dsetList.push_back(data6) ;
1224 return merge(dsetList) ;
1225}
1226
1227
1228
1229////////////////////////////////////////////////////////////////////////////////
1230/// Merge columns of supplied data set(s) with this data set. All
1231/// data sets must have equal number of entries. In case of
1232/// duplicate columns the column of the last dataset in the list
1233/// prevails
1234
1235bool RooDataSet::merge(list<RooDataSet*>dsetList)
1236{
1237
1238 checkInit() ;
1239 // Sanity checks: data sets must have the same size
1240 for (list<RooDataSet*>::iterator iter = dsetList.begin() ; iter != dsetList.end() ; ++iter) {
1241 if (numEntries()!=(*iter)->numEntries()) {
1242 coutE(InputArguments) << "RooDataSet::merge(" << GetName() << ") ERROR: datasets have different size" << endl ;
1243 return true ;
1244 }
1245 }
1246
1247 // Extend vars with elements of other dataset
1248 list<RooAbsDataStore*> dstoreList ;
1249 for (list<RooDataSet*>::iterator iter = dsetList.begin() ; iter != dsetList.end() ; ++iter) {
1250 _vars.addClone((*iter)->_vars,true) ;
1251 dstoreList.push_back((*iter)->store()) ;
1252 }
1253
1254 // Merge data stores
1255 RooAbsDataStore* mergedStore = _dstore->merge(_vars,dstoreList) ;
1256 mergedStore->SetName(_dstore->GetName()) ;
1257 mergedStore->SetTitle(_dstore->GetTitle()) ;
1258
1259 // Replace current data store with merged store
1260 _dstore.reset(mergedStore);
1261
1262 initialize(_wgtVar?_wgtVar->GetName():nullptr) ;
1263 return false ;
1264}
1265
1266
1267////////////////////////////////////////////////////////////////////////////////
1268/// Add all data points of given data set to this data set.
1269/// Observable in 'data' that are not in this dataset
1270/// with not be transferred
1271
1273{
1274 checkInit() ;
1275 _dstore->append(*data._dstore) ;
1276}
1277
1278
1279
1280////////////////////////////////////////////////////////////////////////////////
1281/// Add a column with the values of the given (function) argument
1282/// to this dataset. The function value is calculated for each
1283/// event using the observable values of each event in case the
1284/// function depends on variables with names that are identical
1285/// to the observable names in the dataset
1286
1288{
1289 checkInit() ;
1290 std::unique_ptr<RooAbsArg> ret{_dstore->addColumn(var,adjustRange)};
1291 RooAbsArg* retPtr = ret.get();
1292 _vars.addOwned(std::move(ret));
1293 initialize(_wgtVar?_wgtVar->GetName():nullptr) ;
1294 return retPtr;
1295}
1296
1297
1298////////////////////////////////////////////////////////////////////////////////
1299/// Add a column with the values of the given list of (function)
1300/// argument to this dataset. Each function value is calculated for
1301/// each event using the observable values of the event in case the
1302/// function depends on variables with names that are identical to
1303/// the observable names in the dataset
1304
1306{
1307 auto * holderSet = new RooArgSet{};
1308 for(RooAbsArg * var : varList) {
1309 holderSet->add(*addColumn(*var));
1310 }
1311 return holderSet;
1312}
1313
1314
1315
1316
1317
1318////////////////////////////////////////////////////////////////////////////////
1319/// Special plot method for 'X-Y' datasets used in \f$ \chi^2 \f$ fitting.
1320/// For general plotting, see RooAbsData::plotOn().
1321///
1322/// These datasets
1323/// have one observable (X) and have weights (Y) and associated errors.
1324/// <table>
1325/// <tr><th> Contents options <th> Effect
1326/// <tr><td> YVar(RooRealVar& var) <td> Designate specified observable as 'y' variable
1327/// If not specified, the event weight will be the y variable
1328/// <tr><th> Histogram drawing options <th> Effect
1329/// <tr><td> DrawOption(const char* opt) <td> Select ROOT draw option for resulting TGraph object
1330/// <tr><td> LineStyle(Int_t style) <td> Select line style by ROOT line style code, default is solid
1331/// <tr><td> LineColor(Int_t color) <td> Select line color by ROOT color code, default is black
1332/// <tr><td> LineWidth(Int_t width) <td> Select line with in pixels, default is 3
1333/// <tr><td> MarkerStyle(Int_t style) <td> Select the ROOT marker style, default is 21
1334/// <tr><td> MarkerColor(Int_t color) <td> Select the ROOT marker color, default is black
1335/// <tr><td> MarkerSize(double size) <td> Select the ROOT marker size
1336/// <tr><td> Rescale(double factor) <td> Apply global rescaling factor to histogram
1337/// <tr><th> Misc. other options <th> Effect
1338/// <tr><td> Name(const chat* name) <td> Give curve specified name in frame. Useful if curve is to be referenced later
1339/// <tr><td> Invisible(bool flag) <td> Add curve to frame, but do not display. Useful in combination AddTo()
1340/// </table>
1341
1342RooPlot* RooDataSet::plotOnXY(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
1343 const RooCmdArg& arg3, const RooCmdArg& arg4,
1344 const RooCmdArg& arg5, const RooCmdArg& arg6,
1345 const RooCmdArg& arg7, const RooCmdArg& arg8) const
1346{
1347 checkInit() ;
1348
1349 RooLinkedList argList ;
1350 argList.Add((TObject*)&arg1) ; argList.Add((TObject*)&arg2) ;
1351 argList.Add((TObject*)&arg3) ; argList.Add((TObject*)&arg4) ;
1352 argList.Add((TObject*)&arg5) ; argList.Add((TObject*)&arg6) ;
1353 argList.Add((TObject*)&arg7) ; argList.Add((TObject*)&arg8) ;
1354
1355 // Process named arguments
1356 RooCmdConfig pc("RooDataSet::plotOnXY(" + std::string(GetName()) + ")");
1357 pc.defineString("drawOption","DrawOption",0,"P") ;
1358 pc.defineString("histName","Name",0,"") ;
1359 pc.defineInt("lineColor","LineColor",0,-999) ;
1360 pc.defineInt("lineStyle","LineStyle",0,-999) ;
1361 pc.defineInt("lineWidth","LineWidth",0,-999) ;
1362 pc.defineInt("markerColor","MarkerColor",0,-999) ;
1363 pc.defineInt("markerStyle","MarkerStyle",0,8) ;
1364 pc.defineDouble("markerSize","MarkerSize",0,-999) ;
1365 pc.defineInt("fillColor","FillColor",0,-999) ;
1366 pc.defineInt("fillStyle","FillStyle",0,-999) ;
1367 pc.defineInt("histInvisible","Invisible",0,0) ;
1368 pc.defineDouble("scaleFactor","Rescale",0,1.) ;
1369 pc.defineObject("xvar","XVar",0,nullptr) ;
1370 pc.defineObject("yvar","YVar",0,nullptr) ;
1371
1372
1373 // Process & check varargs
1374 pc.process(argList) ;
1375 if (!pc.ok(true)) {
1376 return frame ;
1377 }
1378
1379 // Extract values from named arguments
1380 const char* drawOptions = pc.getString("drawOption") ;
1381 Int_t histInvisible = pc.getInt("histInvisible") ;
1382 const char* histName = pc.getString("histName",nullptr,true) ;
1383 double scaleFactor = pc.getDouble("scaleFactor") ;
1384
1385 RooRealVar* xvar = (RooRealVar*) _vars.find(frame->getPlotVar()->GetName()) ;
1386
1387 // Determine Y variable (default is weight, if present)
1388 RooRealVar* yvar = (RooRealVar*)(pc.getObject("yvar")) ;
1389
1390 // Sanity check. XY plotting only applies to weighted datasets if no YVar is specified
1391 if (!_wgtVar && !yvar) {
1392 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR: no YVar() argument specified and dataset is not weighted" << endl ;
1393 return nullptr ;
1394 }
1395
1396 RooRealVar* dataY = yvar ? (RooRealVar*) _vars.find(yvar->GetName()) : nullptr ;
1397 if (yvar && !dataY) {
1398 coutE(InputArguments) << "RooDataSet::plotOnXY(" << GetName() << ") ERROR on YVar() argument, dataset does not contain a variable named " << yvar->GetName() << endl ;
1399 return nullptr ;
1400 }
1401
1402
1403 // Make RooHist representing XY contents of data
1404 RooHist* graph = new RooHist ;
1405 if (histName) {
1406 graph->SetName(histName) ;
1407 } else {
1408 graph->SetName(("hxy_" + std::string(GetName())).c_str());
1409 }
1410
1411 for (int i=0 ; i<numEntries() ; i++) {
1412 get(i) ;
1413 double x = xvar->getVal() ;
1414 double exlo = xvar->getErrorLo() ;
1415 double exhi = xvar->getErrorHi() ;
1416 double y,eylo,eyhi ;
1417 if (!dataY) {
1418 y = weight() ;
1419 weightError(eylo,eyhi) ;
1420 } else {
1421 y = dataY->getVal() ;
1422 eylo = dataY->getErrorLo() ;
1423 eyhi = dataY->getErrorHi() ;
1424 }
1425 graph->addBinWithXYError(x,y,-1*exlo,exhi,-1*eylo,eyhi,scaleFactor) ;
1426 }
1427
1428 // Adjust style options according to named arguments
1429 Int_t lineColor = pc.getInt("lineColor") ;
1430 Int_t lineStyle = pc.getInt("lineStyle") ;
1431 Int_t lineWidth = pc.getInt("lineWidth") ;
1432 Int_t markerColor = pc.getInt("markerColor") ;
1433 Int_t markerStyle = pc.getInt("markerStyle") ;
1434 Size_t markerSize = pc.getDouble("markerSize") ;
1435 Int_t fillColor = pc.getInt("fillColor") ;
1436 Int_t fillStyle = pc.getInt("fillStyle") ;
1437
1438 if (lineColor!=-999) graph->SetLineColor(lineColor) ;
1439 if (lineStyle!=-999) graph->SetLineStyle(lineStyle) ;
1440 if (lineWidth!=-999) graph->SetLineWidth(lineWidth) ;
1441 if (markerColor!=-999) graph->SetMarkerColor(markerColor) ;
1442 if (markerStyle!=-999) graph->SetMarkerStyle(markerStyle) ;
1443 if (markerSize!=-999) graph->SetMarkerSize(markerSize) ;
1444 if (fillColor!=-999) graph->SetFillColor(fillColor) ;
1445 if (fillStyle!=-999) graph->SetFillStyle(fillStyle) ;
1446
1447 // Add graph to frame
1448 frame->addPlotable(graph,drawOptions,histInvisible) ;
1449
1450 return frame ;
1451}
1452
1453
1454
1455
1456////////////////////////////////////////////////////////////////////////////////
1457/// Read given list of ascii files, and construct a data set, using the given
1458/// ArgList as structure definition.
1459/// \param fileList Multiple file names, comma separated. Each
1460/// file is optionally prefixed with 'commonPath' if such a path is
1461/// provided
1462///
1463/// \param varList Specify the dimensions of the dataset to be built.
1464/// This list describes the order in which these dimensions appear in the
1465/// ascii files to be read.
1466/// Each line in the ascii file should contain N white-space separated
1467/// tokens, with N the number of args in `varList`. Any text beyond
1468/// N tokens will be ignored with a warning message.
1469/// (NB: This is the default output of RooArgList::writeToStream())
1470///
1471/// \param verbOpt `Q` be quiet, `D` debug mode (verbose)
1472///
1473/// \param commonPath All filenames in `fileList` will be prefixed with this optional path.
1474///
1475/// \param indexCatName Interpret the data as belonging to category `indexCatName`.
1476/// When multiple files are read, a RooCategory arg in `varList` can
1477/// optionally be designated to hold information about the source file
1478/// of each data point. This feature is enabled by giving the name
1479/// of the (already existing) category variable in `indexCatName`.
1480///
1481/// \attention If the value of any of the variables on a given line exceeds the
1482/// fit range associated with that dimension, the entire line will be
1483/// ignored. A warning message is printed in each case, unless the
1484/// `Q` verbose option is given. The number of events read and skipped
1485/// is always summarized at the end.
1486///
1487/// If no further information is given a label name 'fileNNN' will
1488/// be assigned to each event, where NNN is the sequential number of
1489/// the source file in `fileList`.
1490///
1491/// Alternatively, it is possible to override the default label names
1492/// of the index category by specifying them in the fileList string:
1493/// When instead of `file1.txt,file2.txt` the string
1494/// `file1.txt:FOO,file2.txt:BAR` is specified, a state named "FOO"
1495/// is assigned to the index category for each event originating from
1496/// file1.txt. The labels FOO,BAR may be predefined in the index
1497/// category via defineType(), but don't have to be.
1498///
1499/// Finally, one can also assign the same label to multiple files,
1500/// either by specifying `file1.txt:FOO,file2,txt:FOO,file3.txt:BAR`
1501/// or `file1.txt,file2.txt:FOO,file3.txt:BAR`.
1502///
1503
1504RooDataSet *RooDataSet::read(const char *fileList, const RooArgList &varList,
1505 const char *verbOpt, const char* commonPath,
1506 const char* indexCatName) {
1507 // Make working copy of variables list
1508 RooArgList variables(varList) ;
1509
1510 // Append blinding state category to variable list if not already there
1511 bool ownIsBlind(true) ;
1512 RooAbsArg* blindState = variables.find("blindState") ;
1513 if (!blindState) {
1514 blindState = new RooCategory("blindState","Blinding State") ;
1515 variables.add(*blindState) ;
1516 } else {
1517 ownIsBlind = false ;
1518 if (blindState->IsA()!=RooCategory::Class()) {
1519 oocoutE(nullptr,DataHandling) << "RooDataSet::read: ERROR: variable list already contains"
1520 << "a non-RooCategory blindState member" << endl ;
1521 return nullptr ;
1522 }
1523 oocoutW(nullptr,DataHandling) << "RooDataSet::read: WARNING: recycling existing "
1524 << "blindState category in variable list" << endl ;
1525 }
1526 RooCategory* blindCat = (RooCategory*) blindState ;
1527
1528 // Configure blinding state category
1529 blindCat->setAttribute("Dynamic") ;
1530 blindCat->defineType("Normal",0) ;
1531 blindCat->defineType("Blind",1) ;
1532
1533 // parse the option string
1534 TString opts= verbOpt;
1535 opts.ToLower();
1536 bool verbose= !opts.Contains("q");
1537 bool debug= opts.Contains("d");
1538
1539 auto data = std::make_unique<RooDataSet>("dataset", fileList, variables);
1540 if (ownIsBlind) { variables.remove(*blindState) ; delete blindState ; }
1541 if(!data) {
1542 oocoutE(nullptr,DataHandling) << "RooDataSet::read: unable to create a new dataset"
1543 << endl;
1544 return nullptr;
1545 }
1546
1547 // Redirect blindCat to point to the copy stored in the data set
1548 blindCat = (RooCategory*) data->_vars.find("blindState") ;
1549
1550 // Find index category, if requested
1551 RooCategory *indexCat = nullptr;
1552 //RooCategory *indexCatOrig = 0;
1553 if (indexCatName) {
1554 RooAbsArg* tmp = nullptr;
1555 tmp = data->_vars.find(indexCatName) ;
1556 if (!tmp) {
1557 oocoutE(data.get(),DataHandling) << "RooDataSet::read: no index category named "
1558 << indexCatName << " in supplied variable list" << endl ;
1559 return nullptr;
1560 }
1561 if (tmp->IsA()!=RooCategory::Class()) {
1562 oocoutE(data.get(),DataHandling) << "RooDataSet::read: variable " << indexCatName
1563 << " is not a RooCategory" << endl ;
1564 return nullptr;
1565 }
1566 indexCat = static_cast<RooCategory*>(tmp);
1567
1568 // Prevent RooArgSet from attempting to read in indexCat
1569 indexCat->setAttribute("Dynamic") ;
1570 }
1571
1572
1573 Int_t outOfRange(0) ;
1574
1575 // Loop over all names in comma separated list
1576 Int_t fileSeqNum(0);
1577 for (const auto& filename : ROOT::Split(std::string(fileList), ", ")) {
1578 // Determine index category number, if this option is active
1579 if (indexCat) {
1580
1581 // Find and detach optional file category name
1582 const char *catname = strchr(filename.c_str(),':');
1583
1584 if (catname) {
1585 // Use user category name if provided
1586 catname++ ;
1587
1588 if (indexCat->hasLabel(catname)) {
1589 // Use existing category index
1590 indexCat->setLabel(catname);
1591 } else {
1592 // Register cat name
1593 indexCat->defineType(catname,fileSeqNum) ;
1594 indexCat->setIndex(fileSeqNum) ;
1595 }
1596 } else {
1597 // Assign autogenerated name
1598 char newLabel[128] ;
1599 snprintf(newLabel,128,"file%03d",fileSeqNum) ;
1600 if (indexCat->defineType(newLabel,fileSeqNum)) {
1601 oocoutE(data.get(), DataHandling) << "RooDataSet::read: Error, cannot register automatic type name " << newLabel
1602 << " in index category " << indexCat->GetName() << endl ;
1603 return nullptr ;
1604 }
1605 // Assign new category number
1606 indexCat->setIndex(fileSeqNum) ;
1607 }
1608 }
1609
1610 oocoutI(data.get(), DataHandling) << "RooDataSet::read: reading file " << filename << endl ;
1611
1612 // Prefix common path
1613 TString fullName(commonPath) ;
1614 fullName.Append(filename) ;
1615 ifstream file(fullName) ;
1616
1617 if (!file.good()) {
1618 oocoutE(data.get(), DataHandling) << "RooDataSet::read: unable to open '"
1619 << filename << "'. Returning nullptr now." << endl;
1620 return nullptr;
1621 }
1622
1623 // double value;
1624 Int_t line(0) ;
1625 bool haveBlindString(false) ;
1626
1627 while(file.good() && !file.eof()) {
1628 line++;
1629 if(debug) oocxcoutD(data.get(),DataHandling) << "reading line " << line << endl;
1630
1631 // process comment lines
1632 if (file.peek() == '#') {
1633 if(debug) oocxcoutD(data.get(),DataHandling) << "skipping comment on line " << line << endl;
1634 } else {
1635 // Read single line
1636 bool readError = variables.readFromStream(file,true,verbose) ;
1637 data->_vars.assign(variables) ;
1638
1639 // Stop on read error
1640 if(!file.good()) {
1641 oocoutE(data.get(), DataHandling) << "RooDataSet::read(static): read error at line " << line << endl ;
1642 break;
1643 }
1644
1645 if (readError) {
1646 outOfRange++ ;
1647 } else {
1648 blindCat->setIndex(haveBlindString) ;
1649 data->fill(); // store this event
1650 }
1651 }
1652
1653 // Skip all white space (including empty lines).
1654 while (isspace(file.peek())) {
1655 char dummy;
1656 file >> std::noskipws >> dummy >> std::skipws;
1657 }
1658 }
1659
1660 file.close();
1661
1662 // get next file name
1663 fileSeqNum++ ;
1664 }
1665
1666 if (indexCat) {
1667 // Copy dynamically defined types from new data set to indexCat in original list
1668 assert(dynamic_cast<RooCategory*>(variables.find(indexCatName)));
1669 const auto origIndexCat = static_cast<RooCategory*>(variables.find(indexCatName));
1670 for (const auto& nameIdx : *indexCat) {
1671 origIndexCat->defineType(nameIdx.first, nameIdx.second);
1672 }
1673 }
1674 oocoutI(data.get(),DataHandling) << "RooDataSet::read: read " << data->numEntries()
1675 << " events (ignored " << outOfRange << " out of range events)" << endl;
1676
1677 return data.release();
1678}
1679
1680
1681
1682
1683////////////////////////////////////////////////////////////////////////////////
1684/// Write the contents of this dataset to an ASCII file with the specified name.
1685/// Each event will be written as a single line containing the written values
1686/// of each observable in the order they were declared in the dataset and
1687/// separated by whitespaces
1688
1689bool RooDataSet::write(const char* filename) const
1690{
1691 // Open file for writing
1692 ofstream ofs(filename) ;
1693 if (ofs.fail()) {
1694 coutE(DataHandling) << "RooDataSet::write(" << GetName() << ") cannot create file " << filename << endl ;
1695 return true ;
1696 }
1697
1698 // Write all lines as arglist in compact mode
1699 coutI(DataHandling) << "RooDataSet::write(" << GetName() << ") writing ASCII file " << filename << endl ;
1700 return write(ofs);
1701}
1702
1703////////////////////////////////////////////////////////////////////////////////
1704/// Write the contents of this dataset to the stream.
1705/// Each event will be written as a single line containing the written values
1706/// of each observable in the order they were declared in the dataset and
1707/// separated by whitespaces
1708
1709bool RooDataSet::write(ostream & ofs) const {
1710 checkInit();
1711
1712 for (Int_t i=0; i<numEntries(); ++i) {
1713 get(i)->writeToStream(ofs,true);
1714 }
1715
1716 if (ofs.fail()) {
1717 coutW(DataHandling) << "RooDataSet::write(" << GetName() << "): WARNING error(s) have occurred in writing" << endl ;
1718 }
1719
1720 return ofs.fail() ;
1721}
1722
1723
1724////////////////////////////////////////////////////////////////////////////////
1725/// Print info about this dataset to the specified output stream.
1726///
1727/// Standard: number of entries
1728/// Shape: list of variables we define & were generated with
1729
1730void RooDataSet::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
1731{
1732 checkInit() ;
1733 RooAbsData::printMultiline(os,contents,verbose,indent) ;
1734 if (_wgtVar) {
1735 os << indent << " Dataset variable \"" << _wgtVar->GetName() << "\" is interpreted as the event weight" << endl ;
1736 }
1737}
1738
1739
1740////////////////////////////////////////////////////////////////////////////////
1741/// Print value of the dataset, i.e. the sum of weights contained in the dataset
1742
1743void RooDataSet::printValue(ostream& os) const
1744{
1745 os << numEntries() << " entries" ;
1746 if (isWeighted()) {
1747 os << " (" << sumEntries() << " weighted)" ;
1748 }
1749}
1750
1751
1752
1753////////////////////////////////////////////////////////////////////////////////
1754/// Print argument of dataset, i.e. the observable names
1755
1756void RooDataSet::printArgs(ostream& os) const
1757{
1758 os << "[" ;
1759 bool first(true) ;
1760 for(RooAbsArg* arg : _varsNoWgt) {
1761 if (first) {
1762 first=false ;
1763 } else {
1764 os << "," ;
1765 }
1766 os << arg->GetName() ;
1767 }
1768 if (_wgtVar) {
1769 os << ",weight:" << _wgtVar->GetName() ;
1770 }
1771 os << "]" ;
1772}
1773
1774
1775
1776////////////////////////////////////////////////////////////////////////////////
1777/// Change the name of this dataset into the given name
1778
1779void RooDataSet::SetName(const char *name)
1780{
1781 if (_dir) _dir->GetList()->Remove(this);
1782 // We need to use the function from RooAbsData, because it already overrides TNamed::SetName
1784 if (_dir) _dir->GetList()->Add(this);
1785}
1786
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Change the title of this dataset into the given name
1790
1791void RooDataSet::SetNameTitle(const char *name, const char* title)
1792{
1793 SetName(name);
1794 SetTitle(title);
1795}
1796
1797
1798////////////////////////////////////////////////////////////////////////////////
1799/// Stream an object of class RooDataSet.
1800
1802{
1803 if (R__b.IsReading()) {
1804
1805 UInt_t R__s, R__c;
1806 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1807
1808 if (R__v>1) {
1809
1810 // Use new-style streaming for version >1
1811 R__b.ReadClassBuffer(RooDataSet::Class(),this,R__v,R__s,R__c);
1812
1813 } else {
1814
1815 // Legacy dataset conversion happens here. Legacy RooDataSet inherits from RooTreeData
1816 // which in turn inherits from RooAbsData. Manually stream RooTreeData contents on
1817 // file here and convert it into a RooTreeDataStore which is installed in the
1818 // new-style RooAbsData base class
1819
1820 // --- This is the contents of the streamer code of RooTreeData version 1 ---
1821 UInt_t R__s1, R__c1;
1822 Version_t R__v1 = R__b.ReadVersion(&R__s1, &R__c1); if (R__v1) { }
1823
1825 TTree* X_tree(nullptr) ; R__b >> X_tree;
1826 RooArgSet X_truth ; X_truth.Streamer(R__b);
1827 TString X_blindString ; X_blindString.Streamer(R__b);
1828 R__b.CheckByteCount(R__s1, R__c1, TClass::GetClass("RooTreeData"));
1829 // --- End of RooTreeData-v1 streamer
1830
1831 // Construct RooTreeDataStore from X_tree and complete initialization of new-style RooAbsData
1832 _dstore = std::make_unique<RooTreeDataStore>(X_tree,_vars) ;
1833 _dstore->SetName(GetName()) ;
1834 _dstore->SetTitle(GetTitle()) ;
1835 _dstore->checkInit() ;
1836
1837 // This is the contents of the streamer code of RooDataSet version 1
1839 _varsNoWgt.Streamer(R__b);
1840 R__b >> _wgtVar;
1841 R__b.CheckByteCount(R__s, R__c, RooDataSet::IsA());
1842
1843
1844 }
1845 } else {
1847 }
1848}
1849
1850
1851
1852////////////////////////////////////////////////////////////////////////////////
1853/// Convert vector-based storage to tree-based storage. This implementation overrides the base class
1854/// implementation because the latter doesn't transfer weights.
1856{
1858 _dstore = std::make_unique<RooTreeDataStore>(GetName(), GetTitle(), _vars, *_dstore, nullptr, _wgtVar ? _wgtVar->GetName() : nullptr);
1860 }
1861}
1862
1863
1864namespace {
1865
1866 // Compile-time test if we can still use TStrings for the constructors of
1867 // RooDataClasses, either for both name and title or for only one of them.
1868 TString tstr = "tstr";
1869 const char * cstr = "cstr";
1870 RooRealVar x{"x", "x", 1.0};
1871 RooArgSet vars{x};
1872 RooDataSet d1(tstr, tstr, vars);
1873 RooDataSet d2(tstr, cstr, vars);
1874 RooDataSet d3(cstr, tstr, vars);
1875
1876} // namespace
1877
1878
1879void RooDataSet::loadValuesFromSlices(RooCategory &indexCat, std::map<std::string, RooAbsData *> const &slices,
1880 const char *rangeName, RooFormulaVar const *cutVar, const char *cutSpec)
1881{
1882
1883 if (cutVar && cutSpec) {
1884 throw std::invalid_argument("Only one of cutVar or cutSpec should be not a nullptr!");
1885 }
1886
1887 auto &indexCatInData = *static_cast<RooCategory *>(_vars.find(indexCat.GetName()));
1888
1889 for (auto const &item : slices) {
1890 std::unique_ptr<RooDataSet> sliceDataSet;
1891 RooAbsData* sliceData = item.second;
1892
1893 // If we are importing a RooDataHist, first convert it to a RooDataSet
1894 if(sliceData->InheritsFrom(RooDataHist::Class())) {
1895 sliceDataSet = makeDataSetFromDataHist(static_cast<RooDataHist const &>(*sliceData));
1896 sliceData = sliceDataSet.get();
1897 }
1898
1899 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
1900 if (!indexCat.hasLabel(item.first)) {
1901 indexCat.defineType(item.first);
1902 coutI(InputArguments) << "RooDataSet::ctor(" << GetName() << ") defining state \"" << item.first
1903 << "\" in index category " << indexCat.GetName() << std::endl;
1904 }
1905 if (!indexCatInData.hasLabel(item.first)) {
1906 indexCatInData.defineType(item.first);
1907 }
1908 indexCatInData.setLabel(item.first.c_str());
1909 std::unique_ptr<RooFormulaVar> cutVarTmp;
1910 if (cutSpec) {
1911 cutVarTmp = std::make_unique<RooFormulaVar>(cutSpec, cutSpec, *sliceData->get());
1912 cutVar = cutVarTmp.get();
1913 }
1914 _dstore->loadValues(sliceData->store(), cutVar, rangeName);
1915 }
1916}
#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
#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:79
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
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
Class RooCmdConfig is a 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'.
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
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:171
bool _doWeightErrorCheck
! When adding events with weights, check that weights can actually be stored.
Definition RooDataSet.h:183
static void cleanup()
RooArgSet _varsNoWgt
Vars without weight variable.
Definition RooDataSet.h:170
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:187
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:185
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:182
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.
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:531
RooRealVar represents a 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...
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:4075
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.
OwningPtr< T > owningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:50
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:43
bool checkIfRangesOverlap(RooArgSet const &observables, std::vector< std::string > const &rangeNames)
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