Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooDataHist.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 RooDataHist.cxx
19\class RooDataHist
20\ingroup Roofitcore
21
22Container class to hold N-dimensional binned data. Each bin's central
23coordinates in N-dimensional space are represented by a RooArgSet containing RooRealVar, RooCategory
24or RooStringVar objects, thus data can be binned in real and/or discrete dimensions.
25
26There is an unbinned equivalent, RooDataSet.
27
28### Inspecting a datahist
29Inspect a datahist using Print() to get the coordinates and `weight()` to get the bin contents:
30```
31datahist->Print("V");
32datahist->get(0)->Print("V"); std::cout << "w=" << datahist->weight(0) << std::endl;
33datahist->get(1)->Print("V"); std::cout << "w=" << datahist->weight(1) << std::endl;
34...
35```
36
37### Plotting data.
38See RooAbsData::plotOn().
39
40### Creating a datahist using RDataFrame
41See RooAbsDataHelper, rf408_RDataFrameToRooFit.C
42
43**/
44
45#include "RooDataHist.h"
46
47#include "Riostream.h"
48#include "RooMsgService.h"
50#include "RooAbsLValue.h"
51#include "RooArgList.h"
52#include "RooRealVar.h"
53#include "RooMath.h"
54#include "RooBinning.h"
55#include "RooPlot.h"
56#include "RooHistError.h"
57#include "RooCategory.h"
58#include "RooCmdConfig.h"
59#include "RooLinkedListIter.h"
60#include "RooTreeDataStore.h"
61#include "RooVectorDataStore.h"
62#include "RooTrace.h"
63#include "RooFormulaVar.h"
64#include "RooFormula.h"
65#include "RooUniformBinning.h"
66
67#include "RooFitImplHelpers.h"
68
69#include <ROOT/RSpan.hxx>
70#include <ROOT/StringUtils.hxx>
71
72#include "TAxis.h"
73#include "TH1.h"
74#include "TTree.h"
75#include "TBuffer.h"
76#include "TMath.h"
77#include "Math/Util.h"
78
79using std::string, std::ostream;
80
81
82
83////////////////////////////////////////////////////////////////////////////////
84/// Default constructor
85
90
91
92std::unique_ptr<RooAbsDataStore>
94{
96 ? static_cast<std::unique_ptr<RooAbsDataStore>>(std::make_unique<RooTreeDataStore>(name, title, vars))
97 : static_cast<std::unique_ptr<RooAbsDataStore>>(std::make_unique<RooVectorDataStore>(name, title, vars));
98}
99
100
101////////////////////////////////////////////////////////////////////////////////
102/// Constructor of an empty data hist from a RooArgSet defining the dimensions
103/// of the data space. The range and number of bins in each dimensions are taken
104/// from getMin()getMax(),getBins() of each RooAbsArg representing that
105/// dimension.
106///
107/// For real dimensions, the fit range and number of bins can be set independently
108/// of the plot range and number of bins, but it is advisable to keep the
109/// ratio of the plot bin width and the fit bin width an integer value.
110/// For category dimensions, the fit ranges always comprises all defined states
111/// and each state is always has its individual bin
112///
113/// To effectively bin real dimensions with variable bin sizes,
114/// construct a RooThresholdCategory of the real dimension to be binned variably.
115/// Set the thresholds at the desired bin boundaries, and construct the
116/// data hist as a function of the threshold category instead of the real variable.
117RooDataHist::RooDataHist(RooStringView name, RooStringView title, const RooArgSet& vars, const char* binningName) :
118 RooAbsData(name,title,vars)
119{
120 // Initialize datastore
122
123 initialize(binningName) ;
124
126
128}
129
130
131
132////////////////////////////////////////////////////////////////////////////////
133/// Constructor of a data hist from an existing data collection (binned or unbinned)
134/// The RooArgSet 'vars' defines the dimensions of the histogram.
135/// The range and number of bins in each dimensions are taken
136/// from getMin(), getMax(), getBins() of each argument passed.
137///
138/// For real dimensions, the fit range and number of bins can be set independently
139/// of the plot range and number of bins, but it is advisable to keep the
140/// ratio of the plot bin width and the fit bin width an integer value.
141/// For category dimensions, the fit ranges always comprises all defined states
142/// and each state is always has its individual bin
143///
144/// To effectively bin real dimensions with variable bin sizes,
145/// construct a RooThresholdCategory of the real dimension to be binned variably.
146/// Set the thresholds at the desired bin boundaries, and construct the
147/// data hist as a function of the threshold category instead of the real variable.
148///
149/// If the constructed data hist has less dimensions that in source data collection,
150/// all missing dimensions will be projected.
151
153 RooDataHist(name,title,vars)
154{
155 add(data,static_cast<const RooFormulaVar*>(nullptr),wgt);
156}
157
158
159
160////////////////////////////////////////////////////////////////////////////////
161/// Constructor of a data hist from a map of TH1,TH2 or TH3 that are collated into a x+1 dimensional
162/// RooDataHist where the added dimension is a category that labels the input source as defined
163/// in the histMap argument. The state names used in histMap must correspond to predefined states
164/// 'indexCat'
165///
166/// The RooArgList 'vars' defines the dimensions of the histogram.
167/// The ranges and number of bins are taken from the input histogram and must be the same in all histograms
168
170 std::map<string,TH1*> histMap, double wgt) :
171 RooAbsData(name,title,RooArgSet(vars,&indexCat))
172{
173 // Initialize datastore
175
176 importTH1Set(vars, indexCat, histMap, wgt, false) ;
177
180}
181
182
183
184////////////////////////////////////////////////////////////////////////////////
185/// Constructor of a data hist from a map of RooDataHists that are collated into a x+1 dimensional
186/// RooDataHist where the added dimension is a category that labels the input source as defined
187/// in the histMap argument. The state names used in histMap must correspond to predefined states
188/// 'indexCat'
189///
190/// The RooArgList 'vars' defines the dimensions of the histogram.
191/// The ranges and number of bins are taken from the input histogram and must be the same in all histograms
192
194 std::map<string,RooDataHist*> dhistMap, double wgt) :
195 RooAbsData(name,title,RooArgSet(vars,&indexCat))
196{
197 // Initialize datastore
199
200 importDHistSet(vars, indexCat, dhistMap, wgt) ;
201
204}
205
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Constructor of a data hist from an TH1,TH2 or TH3
210/// The RooArgSet 'vars' defines the dimensions of the histogram. The ranges
211/// and number of bins are taken from the input histogram, and the corresponding
212/// values are set accordingly on the arguments in 'vars'
213
214RooDataHist::RooDataHist(RooStringView name, RooStringView title, const RooArgList& vars, const TH1* hist, double wgt) :
215 RooAbsData(name,title,vars)
216{
217 // Initialize datastore
219
220 // Check consistency in number of dimensions
221 if (int(vars.size()) != hist->GetDimension()) {
222 std::stringstream errorMsgStream;
223 errorMsgStream << "RooDataHist::ctor(" << GetName() << ") ERROR: dimension of input histogram must match "
224 << "number of dimension variables";
225 const std::string errorMsg = errorMsgStream.str();
226 coutE(InputArguments) << errorMsg << std::endl;
227 throw std::invalid_argument(errorMsg);
228 }
229
230 importTH1(vars,*hist,wgt, false) ;
231
234}
235
236
237
238////////////////////////////////////////////////////////////////////////////////
239/// Constructor of a binned dataset from a RooArgSet defining the dimensions
240/// of the data space. The range and number of bins in each dimensions are taken
241/// from getMin() getMax(),getBins() of each RooAbsArg representing that
242/// dimension.
243///
244/// <table>
245/// <tr><th> Optional Argument <th> Effect
246/// <tr><td> Import(TH1&, bool impDens) <td> Import contents of the given TH1/2/3 into this binned dataset. The
247/// ranges and binning of the binned dataset are automatically adjusted to
248/// match those of the imported histogram.
249///
250/// Please note: for TH1& with unequal binning _only_,
251/// you should decide if you want to import the absolute bin content,
252/// or the bin content expressed as density. The latter is default and will
253/// result in the same histogram as the original TH1. For certain types of
254/// bin contents (containing efficiencies, asymmetries, or ratio is general)
255/// you should import the absolute value and set impDens to false
256///
257///
258/// <tr><td> Weight(double) <td> Apply given weight factor when importing histograms
259///
260/// <tr><td> Index(RooCategory&) <td> Prepare import of multiple TH1/1/2/3 into a N+1 dimensional RooDataHist
261/// where the extra discrete dimension labels the source of the imported histogram
262/// If the index category defines states for which no histogram is be imported
263/// the corresponding bins will be left empty.
264///
265/// <tr><td> Import(const char*, TH1&) <td> Import a THx to be associated with the given state name of the index category
266/// specified in Index(). If the given state name is not yet defined in the index
267/// category it will be added on the fly. The import command can be specified
268/// multiple times.
269/// <tr><td> Import(map<string,TH1*>&) <td> As above, but allows specification of many imports in a single operation
270/// <tr><td> `GlobalObservables(const RooArgSet&)` <td> Define the set of global observables to be stored in this RooDataHist.
271/// A snapshot of the passed RooArgSet is stored, meaning the values wont't change unexpectedly.
272/// </table>
273///
274
276 const RooCmdArg& arg4,const RooCmdArg& arg5,const RooCmdArg& arg6,const RooCmdArg& arg7,const RooCmdArg& arg8) :
277 RooAbsData(name,title,RooArgSet(vars,static_cast<RooAbsArg*>(RooCmdConfig::decodeObjOnTheFly("RooDataHist::RooDataHist", "IndexCat",0,nullptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8))))
278{
279 // Initialize datastore
281
282 // Define configuration for this method
283 RooCmdConfig pc("RooDataHist::ctor(" + std::string(GetName()) + ")");
284 pc.defineObject("impHist","ImportHisto",0) ;
285 pc.defineInt("impDens","ImportHisto",0) ;
286 pc.defineObject("indexCat","IndexCat",0) ;
287 pc.defineObject("impSliceData","ImportDataSlice",0,nullptr,true) ; // array
288 pc.defineString("impSliceState","ImportDataSlice",0,"",true) ; // array
289 pc.defineDouble("weight","Weight",0,1) ;
290 pc.defineObject("dummy1","ImportDataSliceMany",0) ;
291 pc.defineSet("glObs","GlobalObservables",0,nullptr) ;
292 pc.defineMutex("ImportHisto","ImportDataSlice");
293 pc.defineDependency("ImportDataSlice","IndexCat") ;
294
296 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
297 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
298 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
299 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
300
301 // Process & check varargs
302 pc.process(l) ;
303 if (!pc.ok(true)) {
304 throw std::invalid_argument("Invalid command arguments passed to RooDataHist constructor!");
305 }
306
307 if(pc.getSet("glObs")) setGlobalObservables(*pc.getSet("glObs"));
308
309 TH1* impHist = static_cast<TH1*>(pc.getObject("impHist")) ;
310 bool impDens = pc.getInt("impDens") ;
311 double initWgt = pc.getDouble("weight") ;
312 RooCategory* indexCat = static_cast<RooCategory*>(pc.getObject("indexCat")) ;
313 const char* impSliceNames = pc.getString("impSliceState","",true) ;
314 const RooLinkedList& impSliceHistos = pc.getObjectList("impSliceData") ;
315
316
317 if (impHist) {
318
319 // Initialize importing contents from TH1
321
322 } else if (indexCat) {
323
324
325 // Initialize importing mapped set of RooDataHists and TH1s
326 std::map<std::string,RooDataHist*> dmap ;
327 std::map<std::string,TH1*> hmap ;
328 auto hiter = impSliceHistos.begin() ;
329 for (const auto& token : ROOT::Split(impSliceNames, ",", /*skipEmpty=*/true)) {
330
331 if (!indexCat->hasLabel(token)) {
332 std::stringstream errorMsgStream;
333 errorMsgStream << "RooDataHist::RooDataHist(\"" << GetName() << "\") "
334 << "you are providing import data for the category state \"" << token
335 << "\", but the index category \"" << indexCat->GetName() << "\" has no such state!";
336 const std::string errorMsg = errorMsgStream.str();
337 coutE(InputArguments) << errorMsg << std::endl;
338 throw std::invalid_argument(errorMsg);
339 }
340
341 if(auto dHist = dynamic_cast<RooDataHist*>(*hiter)) {
342 dmap[token] = dHist;
343 }
344 if(auto hHist = dynamic_cast<TH1*>(*hiter)) {
345 hmap[token] = hHist;
346 }
347 ++hiter;
348 }
349 if(!dmap.empty() && !hmap.empty()) {
350 std::stringstream errorMsgStream;
351 errorMsgStream << "RooDataHist::ctor(" << GetName() << ") ERROR: you can't import mix of TH1 and RooDataHist";
352 const std::string errorMsg = errorMsgStream.str();
353 coutE(InputArguments) << errorMsg << std::endl;
354 throw std::invalid_argument(errorMsg);
355 }
356 if (!dmap.empty()) {
357 importDHistSet(vars,*indexCat,dmap,initWgt);
358 }
359 if (!hmap.empty()) {
360 importTH1Set(vars,*indexCat,hmap,initWgt,false);
361 }
362
363
364 } else {
365
366 // Initialize empty
367 initialize();
368 }
369
372
373}
374
375
376
377
378////////////////////////////////////////////////////////////////////////////////
379/// Import data from given TH1/2/3 into this RooDataHist
380
381void RooDataHist::importTH1(const RooArgList& vars, const TH1& histo, double wgt, bool doDensityCorrection)
382{
383 // Adjust binning of internal observables to match that of input THx
384 Int_t offset[3]{0, 0, 0};
385 adjustBinning(vars, histo, offset) ;
386
387 // Initialize internal data structure
388 initialize();
389
390 // Define x,y,z as 1st, 2nd and 3rd observable
391 RooRealVar* xvar = static_cast<RooRealVar*>(_vars.find(vars.at(0)->GetName())) ;
392 RooRealVar* yvar = static_cast<RooRealVar*>(vars.at(1) ? _vars.find(vars.at(1)->GetName()) : nullptr ) ;
393 RooRealVar* zvar = static_cast<RooRealVar*>(vars.at(2) ? _vars.find(vars.at(2)->GetName()) : nullptr ) ;
394
395 // Transfer contents
396 Int_t xmin(0);
397 Int_t ymin(0);
398 Int_t zmin(0);
400 xmin = offset[0] ;
401 if (yvar) {
402 vset.add(*yvar) ;
403 ymin = offset[1] ;
404 }
405 if (zvar) {
406 vset.add(*zvar) ;
407 zmin = offset[2] ;
408 }
409
410 Int_t iX(0);
411 Int_t iY(0);
412 Int_t iz(0);
413 for (iX=0 ; iX < xvar->getBins() ; iX++) {
414 xvar->setBin(iX) ;
415 if (yvar) {
416 for (iY=0 ; iY < yvar->getBins() ; iY++) {
417 yvar->setBin(iY) ;
418 if (zvar) {
419 for (iz=0 ; iz < zvar->getBins() ; iz++) {
420 zvar->setBin(iz) ;
421 double bv = doDensityCorrection ? binVolume(vset) : 1;
422 add(vset,bv*histo.GetBinContent(iX+1+xmin,iY+1+ymin,iz+1+zmin)*wgt,bv*std::pow(histo.GetBinError(iX+1+xmin,iY+1+ymin,iz+1+zmin)*wgt,2)) ;
423 }
424 } else {
425 double bv = doDensityCorrection ? binVolume(vset) : 1;
426 add(vset,bv*histo.GetBinContent(iX+1+xmin,iY+1+ymin)*wgt,bv*std::pow(histo.GetBinError(iX+1+xmin,iY+1+ymin)*wgt,2)) ;
427 }
428 }
429 } else {
430 double bv = doDensityCorrection ? binVolume(vset) : 1 ;
431 add(vset,bv*histo.GetBinContent(iX+1+xmin)*wgt,bv*std::pow(histo.GetBinError(iX+1+xmin)*wgt,2)) ;
432 }
433 }
434
435}
436
437namespace {
438bool checkConsistentAxes(const TH1* first, const TH1* second) {
439 return first->GetDimension() == second->GetDimension()
440 && first->GetNbinsX() == second->GetNbinsX()
441 && first->GetNbinsY() == second->GetNbinsY()
442 && first->GetNbinsZ() == second->GetNbinsZ()
443 && first->GetXaxis()->GetXmin() == second->GetXaxis()->GetXmin()
444 && first->GetXaxis()->GetXmax() == second->GetXaxis()->GetXmax()
445 && (first->GetNbinsY() == 1 || (first->GetYaxis()->GetXmin() == second->GetYaxis()->GetXmin()
446 && first->GetYaxis()->GetXmax() == second->GetYaxis()->GetXmax() ) )
447 && (first->GetNbinsZ() == 1 || (first->GetZaxis()->GetXmin() == second->GetZaxis()->GetXmin()
448 && first->GetZaxis()->GetXmax() == second->GetZaxis()->GetXmax() ) );
449}
450
452
453 // Relative tolerance for bin boundary comparison
454 constexpr double tolerance = 1e-6;
455
456 auto const& vars1 = *h1.get();
457 auto const& vars2 = *h2.get();
458
459 // Check if number of variables and names is consistent
460 if(!vars1.hasSameLayout(vars2)) {
461 return false;
462 }
463
464 for(std::size_t iVar = 0; iVar < vars1.size(); ++iVar) {
465 auto * var1 = dynamic_cast<RooRealVar*>(vars1[iVar]);
466 auto * var2 = dynamic_cast<RooRealVar*>(vars2[iVar]);
467
468 // Check if variables are consistently real-valued
469 if((!var1 && var2) || (var1 && !var2)) return false;
470
471 // Not a real-valued variable
472 if(!var1) continue;
473
474 // Now check the binning
475 auto const& bng1 = var1->getBinning();
476 auto const& bng2 = var2->getBinning();
477
478 // Compare bin numbers
479 if(bng1.numBins() != bng2.numBins()) return false;
480
481 std::size_t nBins = bng1.numBins();
482
483 // Compare bin boundaries
484 for(std::size_t iBin = 0; iBin < nBins; ++iBin) {
485 double v1 = bng1.binLow(iBin);
486 double v2 = bng2.binLow(iBin);
487 if(std::abs((v1 - v2) / v1) > tolerance) return false;
488 }
489 double v1 = bng1.binHigh(nBins - 1);
490 double v2 = bng2.binHigh(nBins - 1);
491 if(std::abs((v1 - v2) / v1) > tolerance) return false;
492 }
493 return true;
494}
495}
496
497
498////////////////////////////////////////////////////////////////////////////////
499/// Import data from given set of TH1/2/3 into this RooDataHist. The category indexCat labels the sources
500/// in the constructed RooDataHist. The stl map provides the mapping between the indexCat state labels
501/// and the import source
502
503void RooDataHist::importTH1Set(const RooArgList& vars, RooCategory& indexCat, std::map<string,TH1*> hmap, double wgt, bool doDensityCorrection)
504{
505 RooCategory* icat = static_cast<RooCategory*>(_vars.find(indexCat.GetName())) ;
506
507 TH1* histo(nullptr) ;
508 bool init(false) ;
509 for (const auto& hiter : hmap) {
510 // Store pointer to first histogram from which binning specification will be taken
511 if (!histo) {
512 histo = hiter.second;
513 } else {
514 if (!checkConsistentAxes(histo, hiter.second)) {
515 coutE(InputArguments) << "Axes of histogram " << hiter.second->GetName() << " are not consistent with first processed "
516 << "histogram " << histo->GetName() << std::endl;
517 throw std::invalid_argument("Axes of inputs for RooDataHist are inconsistent");
518 }
519 }
520 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
521 if (!indexCat.hasLabel(hiter.first)) {
522 indexCat.defineType(hiter.first) ;
523 coutI(InputArguments) << "RooDataHist::importTH1Set(" << GetName() << ") defining state \"" << hiter.first << "\" in index category " << indexCat.GetName() << std::endl ;
524 }
525 if (!icat->hasLabel(hiter.first)) {
526 icat->defineType(hiter.first) ;
527 }
528 }
529
530 // Check consistency in number of dimensions
531 if (histo && int(vars.size()) != histo->GetDimension()) {
532 coutE(InputArguments) << "RooDataHist::importTH1Set(" << GetName() << "): dimension of input histogram must match "
533 << "number of continuous variables" << std::endl ;
534 throw std::invalid_argument("Inputs histograms for RooDataHist are not compatible with dimensions of variables.");
535 }
536
537 // Copy bins and ranges from THx to dimension observables
538 Int_t offset[3] ;
539 adjustBinning(vars,*histo,offset) ;
540
541 // Initialize internal data structure
542 if (!init) {
543 initialize();
544 init = true;
545 }
546
547 // Define x,y,z as 1st, 2nd and 3rd observable
548 RooRealVar* xvar = static_cast<RooRealVar*>(_vars.find(vars.at(0)->GetName())) ;
549 RooRealVar* yvar = static_cast<RooRealVar*>(vars.at(1) ? _vars.find(vars.at(1)->GetName()) : nullptr ) ;
550 RooRealVar* zvar = static_cast<RooRealVar*>(vars.at(2) ? _vars.find(vars.at(2)->GetName()) : nullptr ) ;
551
552 // Transfer contents
553 Int_t xmin(0);
554 Int_t ymin(0);
555 Int_t zmin(0);
557 double volume = xvar->getMax()-xvar->getMin() ;
558 xmin = offset[0] ;
559 if (yvar) {
560 vset.add(*yvar) ;
561 ymin = offset[1] ;
562 volume *= (yvar->getMax()-yvar->getMin()) ;
563 }
564 if (zvar) {
565 vset.add(*zvar) ;
566 zmin = offset[2] ;
567 volume *= (zvar->getMax()-zvar->getMin()) ;
568 }
569 double avgBV = volume / numEntries() ;
570
571 Int_t ic(0);
572 Int_t iX(0);
573 Int_t iY(0);
574 Int_t iz(0);
575 for (ic=0 ; ic < icat->numBins(nullptr) ; ic++) {
576 icat->setBin(ic) ;
577 histo = hmap[icat->getCurrentLabel()] ;
578 for (iX=0 ; iX < xvar->getBins() ; iX++) {
579 xvar->setBin(iX) ;
580 if (yvar) {
581 for (iY=0 ; iY < yvar->getBins() ; iY++) {
582 yvar->setBin(iY) ;
583 if (zvar) {
584 for (iz=0 ; iz < zvar->getBins() ; iz++) {
585 zvar->setBin(iz) ;
586 double bv = doDensityCorrection ? binVolume(vset)/avgBV : 1;
587 add(vset,bv*histo->GetBinContent(iX+1+xmin,iY+1+ymin,iz+1+zmin)*wgt,bv*std::pow(histo->GetBinError(iX+1+xmin,iY+1+ymin,iz+1+zmin)*wgt,2)) ;
588 }
589 } else {
590 double bv = doDensityCorrection ? binVolume(vset)/avgBV : 1;
591 add(vset,bv*histo->GetBinContent(iX+1+xmin,iY+1+ymin)*wgt,bv*std::pow(histo->GetBinError(iX+1+xmin,iY+1+ymin)*wgt,2)) ;
592 }
593 }
594 } else {
595 double bv = doDensityCorrection ? binVolume(vset)/avgBV : 1;
596 add(vset,bv*histo->GetBinContent(iX+1+xmin)*wgt,bv*std::pow(histo->GetBinError(iX+1+xmin)*wgt,2)) ;
597 }
598 }
599 }
600
601}
602
603
604
605////////////////////////////////////////////////////////////////////////////////
606/// Import data from given set of TH1/2/3 into this RooDataHist. The category indexCat labels the sources
607/// in the constructed RooDataHist. The stl map provides the mapping between the indexCat state labels
608/// and the import source
609
610void RooDataHist::importDHistSet(const RooArgList & /*vars*/, RooCategory &indexCat,
611 std::map<std::string, RooDataHist *> dmap, double initWgt)
612{
613 auto *icat = static_cast<RooCategory *>(_vars.find(indexCat.GetName()));
614
615 RooDataHist *dhistForBinning = nullptr;
616
617 for (const auto &diter : dmap) {
618
619 std::string const &label = diter.first;
620 RooDataHist *dhist = diter.second;
621
622 if (!dhistForBinning) {
624 } else {
626 coutE(InputArguments) << "Layout or binning of histogram " << dhist->GetName()
627 << " is not consistent with first processed "
628 << "histogram " << dhistForBinning->GetName() << std::endl;
629 throw std::invalid_argument("Layout or binning of inputs for RooDataHist is inconsistent");
630 }
631 }
632
633 // Define state labels in index category (both in provided indexCat and in internal copy in dataset)
634 if (!indexCat.hasLabel(label)) {
635 indexCat.defineType(label);
636 coutI(InputArguments) << "RooDataHist::importDHistSet(" << GetName() << ") defining state \"" << label
637 << "\" in index category " << indexCat.GetName() << std::endl;
638 }
639 if (!icat->hasLabel(label)) {
640 icat->defineType(label);
641 }
642 }
643
644 // adjust the binning of the created histogram
646 auto *ourVar = dynamic_cast<RooRealVar *>(_vars.find(theirVar->GetName()));
647 if (!theirVar || !ourVar)
648 continue;
649 ourVar->setBinning(theirVar->getBinning());
650 }
651
652 initialize();
653
654 for (const auto &diter : dmap) {
655 std::string const &label = diter.first;
656 RooDataHist *dhist = diter.second;
657
658 icat->setLabel(label.c_str());
659
660 // Transfer contents
661 for (Int_t i = 0; i < dhist->numEntries(); i++) {
662 _vars.assign(*dhist->get(i));
663 add(_vars, dhist->weight() * initWgt, pow(dhist->weightError(SumW2), 2));
664 }
665 }
666}
667
668////////////////////////////////////////////////////////////////////////////////
669/// Helper doing the actual work of adjustBinning().
670
673{
674 const std::string ourVarName(ourVar->GetName() ? ourVar->GetName() : "");
675 const std::string ownName(GetName() ? GetName() : "");
676 // RooRealVar is derived from RooAbsRealLValue which is itself
677 // derived from RooAbsReal and a virtual class RooAbsLValue
678 // supplying setter functions, check if ourVar is indeed derived
679 // as real
680 if (!dynamic_cast<RooAbsReal *>(ourVar)) {
681 coutE(InputArguments) << "RooDataHist::adjustBinning(" << ownName << ") ERROR: dimension " << ourVarName
682 << " must be real\n";
683 throw std::logic_error("Incorrect type object (" + ourVarName +
684 ") passed as argument to RooDataHist::_adjustBinning. Please report this issue.");
685 }
686
687 const double xlo = theirVar.getMin();
688 const double xhi = theirVar.getMax();
689
690 const bool isUniform = !axis.GetXbins()->GetArray();
691 std::unique_ptr<RooAbsBinning> xbins;
692
693 if (!isUniform) {
694 xbins = std::make_unique<RooBinning>(axis.GetNbins(), axis.GetXbins()->GetArray());
695 } else {
696 xbins = std::make_unique<RooUniformBinning>(axis.GetXmin(), axis.GetXmax(), axis.GetNbins());
697 }
698
699 const double tolerance = 1e-6 * xbins->averageBinWidth();
700
701 // Adjust xlo/xhi to nearest boundary
702 const int iBinLo = xbins->binNumber(xlo + tolerance);
703 const int iBinHi = xbins->binNumber(xhi - tolerance);
704 const int nBinsAdj = iBinHi - iBinLo + 1;
705 const double xloAdj = xbins->binLow(iBinLo);
706 const double xhiAdj = xbins->binHigh(iBinHi);
707
708 if (isUniform) {
709 xbins = std::make_unique<RooUniformBinning>(xloAdj, xhiAdj, nBinsAdj);
710 theirVar.setRange(xloAdj, xhiAdj);
711 } else {
712 xbins->setRange(xloAdj, xhiAdj);
713 theirVar.setBinning(*xbins);
714 }
715
716 if (std::abs(xloAdj - xlo) > tolerance || std::abs(xhiAdj - xhi) > tolerance) {
717 coutI(DataHandling) << "RooDataHist::adjustBinning(" << ownName << "): fit range of variable " << ourVarName
718 << " expanded to nearest bin boundaries: [" << xlo << "," << xhi << "] --> [" << xloAdj << ","
719 << xhiAdj << "]"
720 << "\n";
721 }
722
723 ourVar->setBinning(*xbins);
724
725 // The offset is the bin number of the adjusted lower limit of the RooFit
726 // variable in the original TH1 histogram, starting from zero.
727 if (offset) {
728 *offset = axis.FindFixBin(xloAdj + tolerance) - 1;
729 }
730}
731
732////////////////////////////////////////////////////////////////////////////////
733/// Adjust binning specification on first and optionally second and third
734/// observable to binning in given reference TH1. Used by constructors
735/// that import data from an external TH1.
736/// Both the variables in vars and in this RooDataHist are adjusted.
737/// @param vars List with variables that are supposed to have their binning adjusted.
738/// @param href Reference histogram that dictates the binning
739/// @param offset If not nullptr, a possible bin count offset for the axes x,y,z is saved here as Int_t[3]
740
742{
743 auto xvar = static_cast<RooRealVar*>(_vars.find(*vars.at(0)) );
744 _adjustBinning(*static_cast<RooRealVar*>(vars.at(0)), *href.GetXaxis(), xvar, offset ? &offset[0] : nullptr);
745
746 if (vars.at(1)) {
747 auto yvar = static_cast<RooRealVar*>(_vars.find(*vars.at(1)));
748 if (yvar)
749 _adjustBinning(*static_cast<RooRealVar*>(vars.at(1)), *href.GetYaxis(), yvar, offset ? &offset[1] : nullptr);
750 }
751
752 if (vars.at(2)) {
753 auto zvar = static_cast<RooRealVar*>(_vars.find(*vars.at(2)));
754 if (zvar)
755 _adjustBinning(*static_cast<RooRealVar*>(vars.at(2)), *href.GetZaxis(), zvar, offset ? &offset[2] : nullptr);
756 }
757
758}
759
760
761namespace {
762/// Clone external weight arrays, unless the external array is nullptr.
763void cloneArray(double*& ours, const double* theirs, std::size_t n) {
764 if (ours) delete[] ours;
765 ours = nullptr;
766 if (!theirs) return;
767 ours = new double[n];
768 std::copy(theirs, theirs+n, ours);
769}
770
771/// Allocate and initialise an array with desired size and values.
772void initArray(double*& arr, std::size_t n, double val) {
773 if (arr) delete[] arr;
774 arr = nullptr;
775 if (n == 0) return;
776 arr = new double[n];
777 std::fill(arr, arr+n, val);
778}
779}
780
781
782////////////////////////////////////////////////////////////////////////////////
783/// Initialization procedure: allocate weights array, calculate
784/// multipliers needed for N-space to 1-dim array jump table,
785/// and fill the internal tree with all bin center coordinates
786
787void RooDataHist::initialize(const char* binningName, bool fillTree)
788{
789 _lvvars.clear();
790 _lvbins.clear();
791
792 // Fill array of LValue pointers to variables
793 for (unsigned int i = 0; i < _vars.size(); ++i) {
794 if (binningName) {
795 RooRealVar* rrv = dynamic_cast<RooRealVar*>(_vars[i]);
796 if (rrv) {
797 rrv->setBinning(rrv->getBinning(binningName));
798 }
799 }
800
801 auto lvarg = dynamic_cast<RooAbsLValue*>(_vars[i]);
802 assert(lvarg);
803 _lvvars.push_back(lvarg);
804
805 const RooAbsBinning* binning = lvarg->getBinningPtr(nullptr);
806 _lvbins.emplace_back(binning ? binning->clone() : nullptr);
807 }
808
809
810 // Allocate coefficients array
811 _idxMult.resize(_vars.size()) ;
812
813 _arrSize = 1 ;
814 unsigned int n = 0u;
815 for (const auto var : _vars) {
816 auto arg = dynamic_cast<const RooAbsLValue*>(var);
817 assert(arg);
818
819 // Calculate sub-index multipliers for master index
820 for (unsigned int i = 0u; i<n; i++) {
821 _idxMult[i] *= arg->numBins() ;
822 }
823 _idxMult[n++] = 1 ;
824
825 // Calculate dimension of weight array
826 _arrSize *= arg->numBins() ;
827 }
828
829 // Allocate and initialize weight array if necessary
830 if (!_wgt) {
831 initArray(_wgt, _arrSize, 0.);
832 delete[] _errLo; _errLo = nullptr;
833 delete[] _errHi; _errHi = nullptr;
834 delete[] _sumw2; _sumw2 = nullptr;
836
837 // Refill array pointers in data store when reading
838 // from Streamer
839 if (!fillTree) {
841 }
842 }
843
844 if (!fillTree) return ;
845
846 // Fill TTree with bin center coordinates
847 // Calculate plot bins of components from master index
848
849 for (Int_t ibin=0 ; ibin < _arrSize ; ibin++) {
850 Int_t j(0);
851 Int_t idx(0);
852 Int_t tmp(ibin);
853 double theBinVolume(1) ;
854 for (auto arg2 : _lvvars) {
855 idx = tmp / _idxMult[j] ;
856 tmp -= idx*_idxMult[j++] ;
857 arg2->setBin(idx) ;
858 theBinVolume *= arg2->getBinWidth(idx) ;
859 }
861
862 fill() ;
863 }
864
865
866}
867
868
869////////////////////////////////////////////////////////////////////////////////
870
872{
873 if (!_binbounds.empty()) return;
874 for (auto& it : _lvbins) {
875 _binbounds.push_back(std::vector<double>());
876 if (it) {
877 std::vector<double>& bounds = _binbounds.back();
878 bounds.reserve(2 * it->numBins());
879 for (Int_t i = 0; i < it->numBins(); ++i) {
880 bounds.push_back(it->binLow(i));
881 bounds.push_back(it->binHigh(i));
882 }
883 }
884 }
885}
886
887
888////////////////////////////////////////////////////////////////////////////////
889/// Copy constructor
890
892 RooAbsData(other,newname), RooDirItem(), _arrSize(other._arrSize), _idxMult(other._idxMult), _pbinvCache(other._pbinvCache)
893{
894 // Allocate and initialize weight array
895 assert(_arrSize == other._arrSize);
896 cloneArray(_wgt, other._wgt, other._arrSize);
897 cloneArray(_errLo, other._errLo, other._arrSize);
898 cloneArray(_errHi, other._errHi, other._arrSize);
899 cloneArray(_binv, other._binv, other._arrSize);
900 cloneArray(_sumw2, other._sumw2, other._arrSize);
901
902 // Fill array of LValue pointers to variables
903 for (const auto rvarg : _vars) {
904 auto lvarg = dynamic_cast<RooAbsLValue*>(rvarg);
905 assert(lvarg);
906 _lvvars.push_back(lvarg);
907 const RooAbsBinning* binning = lvarg->getBinningPtr(nullptr);
908 _lvbins.emplace_back(binning ? binning->clone() : nullptr) ;
909 }
910
912}
913
914
915////////////////////////////////////////////////////////////////////////////////
916/// Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods
917
918std::unique_ptr<RooAbsData> RooDataHist::reduceEng(const RooArgSet& varSubset, const RooFormulaVar* cutVar, const char* cutRange,
919 std::size_t nStart, std::size_t nStop) const
920{
921 checkInit() ;
924 auto rdh = std::make_unique<RooDataHist>(GetName(), GetTitle(), myVarSubset);
925
926 RooFormulaVar* cloneVar = nullptr;
927 std::unique_ptr<RooArgSet> tmp;
928 if (cutVar) {
929 tmp = std::make_unique<RooArgSet>();
930 // Deep clone cutVar and attach clone to this dataset
931 if (RooArgSet(*cutVar).snapshot(*tmp)) {
932 coutE(DataHandling) << "RooDataHist::reduceEng(" << GetName() << ") Couldn't deep-clone cut variable, abort," << std::endl ;
933 return nullptr;
934 }
935 cloneVar = static_cast<RooFormulaVar*>(tmp->find(*cutVar));
936 cloneVar->attachDataSet(*this) ;
937 }
938
939 double lo;
940 double hi;
941 const std::size_t nevt = nStop < static_cast<std::size_t>(numEntries()) ? nStop : static_cast<std::size_t>(numEntries());
942 for (auto i=nStart; i<nevt ; i++) {
943 const RooArgSet* row = get(i) ;
944
945 bool doSelect(true) ;
946 if (cutRange) {
947 for (const auto arg : *row) {
948 if (!arg->inRange(cutRange)) {
949 doSelect = false ;
950 break ;
951 }
952 }
953 }
954 if (!doSelect) continue ;
955
956 if (!cloneVar || cloneVar->getVal()) {
957 weightError(lo,hi,SumW2) ;
958 rdh->add(*row,weight(),lo*lo) ;
959 }
960 }
961
962 return rdh ;
963}
964
965
966
967////////////////////////////////////////////////////////////////////////////////
968/// Destructor
969
971{
972 delete[] _wgt;
973 delete[] _errLo;
974 delete[] _errHi;
975 delete[] _sumw2;
976 delete[] _binv;
977
978 removeFromDir(this) ;
980}
981
982
983
984
985////////////////////////////////////////////////////////////////////////////////
986/// Calculate bin number of the given coordinates. If only a subset of the internal
987/// coordinates are passed, the missing coordinates are taken at their current value.
988/// \param[in] coord Variables that are representing the coordinates.
989/// \param[in] fast If the variables in `coord` and the ones of the data hist have the
990/// same size and layout, `fast` can be set to skip checking that all variables are
991/// present in `coord`.
993 checkInit() ;
994 return calcTreeIndex(coord, fast);
995}
996
998 bool correctForBinSize) const
999{
1000 std::vector<double> vals(_arrSize);
1001 for (std::size_t i = 0; i < vals.size(); ++i) {
1002 vals[i] = correctForBinSize ? _wgt[i] / _binv[i] : _wgt[i];
1003 }
1004 return ctx.buildArg(vals);
1005}
1006
1008 const RooAbsCollection &coords, bool reverse) const
1009{
1010 assert(coords.size() == _vars.size());
1011
1012 std::string code;
1013 int idxMult = 1;
1014
1015 for (std::size_t i = 0; i < _vars.size(); ++i) {
1016
1017 std::size_t iVar = reverse ? _vars.size() - 1 - i : i;
1018 const RooAbsArg *internalVar = _vars[iVar];
1019 const RooAbsArg *theVar = coords[iVar];
1020
1021 const RooAbsBinning *binning = _lvbins[iVar].get();
1022 if (!binning) {
1023 coutE(InputArguments) << "RooHistPdf::weight(" << GetName()
1024 << ") ERROR: Code Squashing currently does not support category values." << std::endl;
1025 return "";
1026 }
1027
1028 code += " + " + binning->translateBinNumber(ctx, *theVar, idxMult);
1029
1030 // Use RooAbsLValue here because it also generalized to categories, which
1031 // is useful in the future. dynamic_cast because it's a cross-cast.
1032 idxMult *= dynamic_cast<RooAbsLValue const *>(internalVar)->numBins();
1033 }
1034
1035 return "(" + code + ")";
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Calculate the bin index corresponding to the coordinates passed as argument.
1040/// \param[in] coords Coordinates. If `fast == false`, these can be partial.
1041/// \param[in] fast Promise that the coordinates in `coords` have the same order
1042/// as the internal coordinates. In this case, values are looked up only by index.
1043std::size_t RooDataHist::calcTreeIndex(const RooAbsCollection& coords, bool fast) const
1044{
1045 // With fast, caller promises that layout of `coords` is identical to our internal `vars`.
1046 // Previously, this was verified with an assert in debug mode like this:
1047 //
1048 // assert(!fast || coords.hasSameLayout(_vars));
1049 //
1050 // However, there are usecases where the externally provided `coords` have
1051 // different names than the internal variables, even though they correspond
1052 // to each other. For example, if the observables in the computation graph
1053 // are renamed with `redirectServers`. Hence, we can't do a meaningful assert
1054 // here.
1055
1056 if (&_vars == &coords)
1057 fast = true;
1058
1059 std::size_t masterIdx = 0;
1060
1061 for (unsigned int i=0; i < _vars.size(); ++i) {
1062 const RooAbsArg* internalVar = _vars[i];
1063 const RooAbsBinning* binning = _lvbins[i].get();
1064
1065 // Find the variable that we need values from.
1066 // That's either the variable directly from the external coordinates
1067 // or we find the external one that has the same name as "internalVar".
1068 const RooAbsArg* theVar = fast ? coords[i] : coords.find(*internalVar);
1069 if (!theVar) {
1070 // Variable is not in external coordinates. Use current internal value.
1072 }
1073 // If fast is on, users promise that the sets have the same layout:
1074 //
1075 // assert(!fast || strcmp(internalVar->GetName(), theVar->GetName()) == 0);
1076 //
1077 // This assert is commented out for the same reasons that applied to the
1078 // other assert explained above.
1079
1080 if (binning) {
1081 assert(dynamic_cast<const RooAbsReal*>(theVar));
1082 const double val = static_cast<const RooAbsReal*>(theVar)->getVal();
1083 masterIdx += _idxMult[i] * binning->binNumber(val);
1084 } else {
1085 // We are a category. No binning.
1086 assert(dynamic_cast<const RooAbsCategoryLValue*>(theVar));
1087 auto cat = static_cast<const RooAbsCategoryLValue*>(theVar);
1088 masterIdx += _idxMult[i] * cat->getBin(static_cast<const char*>(nullptr));
1089 }
1090 }
1091
1092 return masterIdx ;
1093}
1094
1095
1096////////////////////////////////////////////////////////////////////////////////
1097/// Back end function to plotting functionality. Plot RooDataHist on given
1098/// frame in mode specified by plot options 'o'. The main purpose of
1099/// this function is to match the specified binning on 'o' to the
1100/// internal binning of the plot observable in this RooDataHist.
1101/// \note see RooAbsData::plotOnImpl() for plotting options.
1103{
1104 checkInit() ;
1105 if (o.bins) return RooAbsData::plotOnImpl(frame,o) ;
1106
1107 if(!frame) {
1108 coutE(InputArguments) << ClassName() << "::" << GetName() << ":plotOn: frame is null" << std::endl;
1109 return nullptr;
1110 }
1111 auto var= static_cast<RooAbsRealLValue*>(frame->getPlotVar());
1112 if(!var) {
1113 coutE(InputArguments) << ClassName() << "::" << GetName()
1114 << ":plotOn: frame does not specify a plot variable" << std::endl;
1115 return nullptr;
1116 }
1117
1118 auto dataVar = static_cast<RooRealVar*>(_vars.find(*var));
1119 if (!dataVar) {
1120 coutE(InputArguments) << ClassName() << "::" << GetName()
1121 << ":plotOn: dataset doesn't contain plot frame variable" << std::endl;
1122 return nullptr;
1123 }
1124
1125 o.bins = &dataVar->getBinning() ;
1126 return RooAbsData::plotOnImpl(frame,o) ;
1127}
1128
1129
1130////////////////////////////////////////////////////////////////////////////////
1131/// A vectorized version of interpolateDim for boundary safe quadratic
1132/// interpolation of one dimensional histograms.
1133///
1134/// \param[out] output An array of interpolated weights corresponding to the
1135/// values in xVals.
1136/// \param[in] xVals An array of event coordinates for which the weights should be
1137/// calculated.
1138/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1139/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1140/// Underflow bins are assumed to have weight zero and
1141/// overflow bins have weight one. Otherwise, the
1142/// histogram is mirrored at the boundaries for the
1143/// interpolation.
1144
1145void RooDataHist::interpolateQuadratic(double* output, std::span<const double> xVals,
1147{
1148 const std::size_t nBins = numEntries();
1149 const std::size_t nEvents = xVals.size();
1150
1151 RooAbsBinning const& binning = *_lvbins[0];
1152 // Reuse the output buffer for bin indices and zero-initialize it
1153 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1154 std::fill(binIndices, binIndices + nEvents, 0);
1155 binning.binNumbers(xVals.data(), binIndices, nEvents);
1156
1157 // Extend coordinates and weights with one extra point before the first bin
1158 // and one extra point after the last bin. This means the original histogram
1159 // bins span elements 1 to nBins in coordsExt and weightsExt
1160 std::vector<double> coordsExt(nBins+3);
1161 double* binCoords = coordsExt.data() + 2;
1162 binCoords[0] = binning.lowBound() + 0.5*_binv[0];
1163 for (std::size_t binIdx = 1; binIdx < nBins ; ++binIdx) {
1164 if (binning.isUniform()) {
1165 double binWidth = _binv[0];
1166 binCoords[binIdx] = binIdx*binWidth + binCoords[0];
1167 }
1168 else {
1169 double binCentDiff = 0.5*_binv[binIdx-1] + 0.5*_binv[binIdx];
1171 }
1172 }
1173
1174 std::vector<double> weightsExt(nBins+3);
1175 // Fill weights for bins that are inside histogram boundaries
1176 for (std::size_t binIdx = 0; binIdx < nBins; ++binIdx) {
1178 }
1179
1180 if (cdfBoundaries) {
1181 coordsExt[0] = - 1e-10 + binning.lowBound();
1182 weightsExt[0] = 0.;
1183
1184 coordsExt[1] = binning.lowBound();
1185 weightsExt[1] = 0.;
1186
1187 coordsExt[nBins+2] = binning.highBound();
1188 weightsExt[nBins+2] = 1.;
1189 }
1190 else {
1191 // Mirror first two bins and last bin
1192 coordsExt[0] = binCoords[1] - 2*_binv[0] - _binv[1];
1193 weightsExt[0] = weightsExt[3];
1194
1195 coordsExt[1] = binCoords[0] - _binv[0];
1196 weightsExt[1] = weightsExt[2];
1197
1198 coordsExt[nBins+2] = binCoords[nBins-1] + _binv[nBins-1];
1199 weightsExt[nBins+2] = weightsExt[nBins+1];
1200 }
1201
1202 // We use the current bin center and two bin centers on the left for
1203 // interpolation if xVal is to the left of the current bin center
1204 for (std::size_t i = 0; i < nEvents ; ++i) {
1205 double xVal = xVals[i];
1206 std::size_t binIdx = binIndices[i] + 2;
1207
1208 // If xVal is to the right of the current bin center, shift all bin
1209 // coordinates one step to the right and use that for the interpolation
1210 if (xVal > coordsExt[binIdx]) {
1211 binIdx += 1;
1212 }
1213
1214 double x1 = coordsExt[binIdx-2];
1215 double y1 = weightsExt[binIdx-2];
1216
1217 double x2 = coordsExt[binIdx-1];
1218 double y2 = weightsExt[binIdx-1];
1219
1220 double x3 = coordsExt[binIdx];
1221 double y3 = weightsExt[binIdx];
1222
1223 // Evaluate a few repeated factors
1224 double quotient = (x3-x1) / (x2-x1);
1225 double x1Sqrd = x1*x1;
1226 double x3Sqrd = x3*x3;
1227 // Solve coefficients in system of three quadratic equations!
1228 double secondCoeff = (y3 - y1 - (y2-y1) * quotient) / (x3Sqrd - x1Sqrd - (x2*x2 - x1Sqrd) * quotient);
1229 double firstCoeff = (y3 - y1 - secondCoeff*(x3Sqrd - x1Sqrd)) / (x3-x1);
1231 // Get the interpolated weight using the equation of a second degree polynomial
1233 }
1234}
1235
1236
1237////////////////////////////////////////////////////////////////////////////////
1238/// A vectorized version of interpolateDim for boundary safe linear
1239/// interpolation of one dimensional histograms.
1240///
1241/// \param[out] output An array of interpolated weights corresponding to the
1242/// values in xVals.
1243/// \param[in] xVals An array of event coordinates for which the weights should be
1244/// calculated.
1245/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1246/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1247/// Underflow bins are assumed to have weight zero and
1248/// overflow bins have weight one. Otherwise, the
1249/// histogram is mirrored at the boundaries for the
1250/// interpolation.
1251
1252void RooDataHist::interpolateLinear(double* output, std::span<const double> xVals,
1254{
1255 const std::size_t nBins = numEntries();
1256 const std::size_t nEvents = xVals.size();
1257
1258 RooAbsBinning const& binning = *_lvbins[0];
1259 // Reuse the output buffer for bin indices and zero-initialize it
1260 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1261 std::fill(binIndices, binIndices + nEvents, 0);
1262 binning.binNumbers(xVals.data(), binIndices, nEvents);
1263
1264 // Extend coordinates and weights with one extra point before the first bin
1265 // and one extra point after the last bin. This means the original histogram
1266 // bins span elements 1 to nBins in coordsExt and weightsExt
1267 std::vector<double> coordsExt(nBins+2);
1268 double* binCoords = coordsExt.data() + 1;
1269 binCoords[0] = binning.lowBound() + 0.5*_binv[0];
1270 for (std::size_t binIdx = 1; binIdx < nBins ; ++binIdx) {
1271 if (binning.isUniform()) {
1272 double binWidth = _binv[0];
1273 binCoords[binIdx] = binIdx*binWidth + binCoords[0];
1274 }
1275 else {
1276 double binCentDiff = 0.5*_binv[binIdx-1] + 0.5*_binv[binIdx];
1278 }
1279 }
1280
1281 std::vector<double> weightsExt(nBins+2);
1282 // Fill weights for bins that are inside histogram boundaries
1283 for (std::size_t binIdx = 0; binIdx < nBins; ++binIdx) {
1285 }
1286
1287 // Fill weights for bins that are outside histogram boundaries
1288 if (cdfBoundaries) {
1289 coordsExt[0] = binning.lowBound();
1290 weightsExt[0] = 0.;
1291 coordsExt[nBins+1] = binning.highBound();
1292 weightsExt[nBins+1] = 1.;
1293 }
1294 else {
1295 // Mirror first and last bins
1296 coordsExt[0] = binCoords[0] - _binv[0];
1297 weightsExt[0] = weightsExt[1];
1298 coordsExt[nBins+1] = binCoords[nBins-1] + _binv[nBins-1];
1299 weightsExt[nBins+1] = weightsExt[nBins];
1300 }
1301
1302 // Interpolate between current bin center and one bin center to the left
1303 // if xVal is to the left of the current bin center
1304 for (std::size_t i = 0; i < nEvents ; ++i) {
1305 double xVal = xVals[i];
1306 std::size_t binIdx = binIndices[i] + 1;
1307
1308 // If xVal is to the right of the current bin center, interpolate between
1309 // current bin center and one bin center to the right instead
1310 if (xVal > coordsExt[binIdx]) { binIdx += 1; }
1311
1312 double x1 = coordsExt[binIdx-1];
1313 double y1 = weightsExt[binIdx-1];
1314 double x2 = coordsExt[binIdx];
1315 double y2 = weightsExt[binIdx];
1316
1317 // Find coefficients by solving a system of two linear equations
1318 double firstCoeff = (y2-y1) / (x2-x1);
1319 double zerothCoeff = y1 - firstCoeff * x1;
1320 // Get the interpolated weight using the equation of a straight line
1322 }
1323}
1324
1325
1326////////////////////////////////////////////////////////////////////////////////
1327/// A vectorized version of RooDataHist::weight() for one dimensional histograms
1328/// with up to one dimensional interpolation.
1329/// \param[out] output An array of weights corresponding the values in xVals.
1330/// \param[in] xVals An array of coordinates for which the weights should be
1331/// calculated.
1332/// \param[in] intOrder Interpolation order; 0th and 1st order are supported.
1333/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1334/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1335/// Underflow bins are assumed to have weight zero and
1336/// overflow bins have weight one. Otherwise, the
1337/// histogram is mirrored at the boundaries for the
1338/// interpolation.
1339
1340void RooDataHist::weights(double* output, std::span<double const> xVals, int intOrder, bool correctForBinSize, bool cdfBoundaries)
1341{
1342 auto const nEvents = xVals.size();
1343
1344 if (intOrder == 0) {
1345 RooAbsBinning const& binning = *_lvbins[0];
1346
1347 // Reuse the output buffer for bin indices and zero-initialize it
1348 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1349 std::fill(binIndices, binIndices + nEvents, 0);
1350 binning.binNumbers(xVals.data(), binIndices, nEvents);
1351
1352 for (std::size_t i=0; i < nEvents; ++i) {
1353 auto binIdx = binIndices[i];
1355 }
1356 }
1357 else if (intOrder == 1) {
1359 }
1360 else if (intOrder == 2) {
1362 }
1363 else {
1364 // Higher dimensional scenarios not yet implemented
1365 coutE(InputArguments) << "RooDataHist::weights(" << GetName() << ") interpolation in "
1366 << intOrder << " dimensions not yet implemented" << std::endl ;
1367 // Fall back to 1st order interpolation
1369 }
1370}
1371
1372
1373////////////////////////////////////////////////////////////////////////////////
1374/// A faster version of RooDataHist::weight that assumes the passed arguments
1375/// are aligned with the histogram variables.
1376/// \param[in] bin Coordinates for which the weight should be calculated.
1377/// Has to be aligned with the internal histogram variables.
1378/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1379/// used for the interpolation. If zero, the bare weight for
1380/// the bin enclosing the coordinatesis returned.
1381/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1382/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1383/// underflow bins are assumed to have weight zero and
1384/// overflow bins have weight one. Otherwise, the
1385/// histogram is mirrored at the boundaries for the
1386/// interpolation.
1387
1389{
1390 checkInit() ;
1391
1392 // Handle illegal intOrder values
1393 if (intOrder<0) {
1394 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") ERROR: interpolation order must be positive" << std::endl ;
1395 return 0 ;
1396 }
1397
1398 // Handle no-interpolation case
1399 if (intOrder==0) {
1400 const auto idx = calcTreeIndex(bin, true);
1401 return correctForBinSize ? _wgt[idx] / _binv[idx] : _wgt[idx];
1402 }
1403
1404 // Handle all interpolation cases
1406}
1407
1408
1409////////////////////////////////////////////////////////////////////////////////
1410/// Return the weight at given coordinates with optional interpolation.
1411/// \param[in] bin Coordinates for which the weight should be calculated.
1412/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1413/// used for the interpolation. If zero, the bare weight for
1414/// the bin enclosing the coordinatesis returned.
1415/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1416/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1417/// underflow bins are assumed to have weight zero and
1418/// overflow bins have weight one. Otherwise, the
1419/// histogram is mirrored at the boundaries for the
1420/// interpolation.
1421/// \param[in] oneSafe Ignored.
1422
1423double RooDataHist::weight(const RooArgSet& bin, Int_t intOrder, bool correctForBinSize, bool cdfBoundaries, bool /*oneSafe*/)
1424{
1425 checkInit() ;
1426
1427 // Handle illegal intOrder values
1428 if (intOrder<0) {
1429 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") ERROR: interpolation order must be positive" << std::endl ;
1430 return 0 ;
1431 }
1432
1433 // Handle no-interpolation case
1434 if (intOrder==0) {
1435 const auto idx = calcTreeIndex(bin, false);
1436 return correctForBinSize ? _wgt[idx] / _binv[idx] : _wgt[idx];
1437 }
1438
1439 // Handle all interpolation cases
1440 _vars.assignValueOnly(bin) ;
1441
1443}
1444
1445
1446////////////////////////////////////////////////////////////////////////////////
1447/// Return the weight at given coordinates with interpolation.
1448/// \param[in] bin Coordinates for which the weight should be calculated.
1449/// Has to be aligned with the internal histogram variables.
1450/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1451/// used for the interpolation.
1452/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1453/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1454/// underflow bins are assumed to have weight zero and
1455/// overflow bins have weight one. Otherwise, the
1456/// histogram is mirrored at the boundaries for the
1457/// interpolation.
1458
1460 VarInfo const& varInfo = getVarInfo();
1461
1462 const auto centralIdx = calcTreeIndex(bin, true);
1463
1464 double wInt{0} ;
1465 if (varInfo.nRealVars == 1) {
1466
1467 // buffer needs to be 2 x (interpolation order + 1), with the factor 2 for x and y.
1468 _interpolationBuffer.resize(2 * intOrder + 2);
1469
1470 // 1-dimensional interpolation
1471 auto const& realX = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx1]);
1473
1474 } else if (varInfo.nRealVars == 2) {
1475
1476 // buffer needs to be 2 x 2 x (interpolation order + 1), with one factor 2
1477 // for x and y, and the other for the number of dimensions.
1478 _interpolationBuffer.resize(4 * intOrder + 4);
1479
1480 // 2-dimensional interpolation
1481 auto const& realX = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx1]);
1482 auto const& realY = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx2]);
1483 double xval = realX.getVal() ;
1484 double yval = realY.getVal() ;
1485
1486 RooAbsBinning const& binningY = realY.getBinning();
1487
1488 int ybinC = binningY.binNumber(yval) ;
1489 int ybinLo = ybinC-intOrder/2 - ((yval<binningY.binCenter(ybinC))?1:0) ;
1490 int ybinM = binningY.numBins() ;
1491
1492 auto idxMultY = _idxMult[varInfo.realVarIdx2];
1494
1495 // Use a class-member buffer to avoid repeated heap allocations.
1496 double * yarr = _interpolationBuffer.data() + 2 * intOrder + 2; // add offset to skip part reserved for other dim
1497 double * xarr = yarr + intOrder + 1;
1498 for (int i=ybinLo ; i<=intOrder+ybinLo ; i++) {
1499 int ibin ;
1500 if (i>=0 && i<ybinM) {
1501 // In range
1502 ibin = i ;
1503 xarr[i-ybinLo] = binningY.binCenter(ibin) ;
1504 } else if (i>=ybinM) {
1505 // Overflow: mirror
1506 ibin = 2*ybinM-i-1 ;
1507 xarr[i-ybinLo] = 2*binningY.highBound()-binningY.binCenter(ibin) ;
1508 } else {
1509 // Underflow: mirror
1510 ibin = -i -1;
1511 xarr[i-ybinLo] = 2*binningY.lowBound()-binningY.binCenter(ibin) ;
1512 }
1515 }
1516
1517 if (gDebug>7) {
1518 std::cout << "RooDataHist interpolating data is" << std::endl ;
1519 std::cout << "xarr = " ;
1520 for (int q=0; q<=intOrder ; q++) std::cout << xarr[q] << " " ;
1521 std::cout << " yarr = " ;
1522 for (int q=0; q<=intOrder ; q++) std::cout << yarr[q] << " " ;
1523 std::cout << std::endl ;
1524 }
1526
1527 } else {
1528
1529 // Higher dimensional scenarios not yet implemented
1530 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") interpolation in "
1531 << varInfo.nRealVars << " dimensions not yet implemented" << std::endl ;
1533
1534 }
1535
1536 return wInt ;
1537}
1538
1539
1541 if (!_errLo || !_errHi) {
1542 initArray(_errLo, _arrSize, -1.);
1543 initArray(_errHi, _arrSize, -1.);
1545 }
1546}
1547
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Return the asymmetric errors on the current weight.
1551/// \note see weightError(ErrorType) const for symmetric error.
1552/// \param[out] lo Low error.
1553/// \param[out] hi High error.
1554/// \param[in] etype Type of error to compute. May throw if not supported.
1555/// Supported errors are
1556/// - `Poisson` Default. Asymmetric Poisson errors (68% CL).
1557/// - `SumW2` The square root of the sum of weights. (Symmetric).
1558/// - `None` Return zero.
1559void RooDataHist::weightError(double& lo, double& hi, ErrorType etype) const
1560{
1561 checkInit() ;
1562
1563 switch (etype) {
1564
1565 case Auto:
1566 throw std::invalid_argument("RooDataHist::weightError(" + std::string(GetName()) + ") error type Auto not allowed here");
1567 break ;
1568
1569 case Expected:
1570 throw std::invalid_argument("RooDataHist::weightError(" + std::string(GetName()) + ") error type Expected not allowed here");
1571 break ;
1572
1573 case Poisson:
1574 if (_errLo && _errLo[_curIndex] >= 0.0) {
1575 // Weight is preset or precalculated
1576 lo = _errLo[_curIndex];
1577 hi = _errHi[_curIndex];
1578 return ;
1579 }
1580
1581 // We didn't track asymmetric errors so far, so now we need to allocate
1583
1584 // Calculate poisson errors
1585 double ym;
1586 double yp;
1587 RooHistError::instance().getPoissonInterval(Int_t(weight()+0.5),ym,yp,1) ;
1590 lo = _errLo[_curIndex];
1591 hi = _errHi[_curIndex];
1592 return ;
1593
1594 case SumW2:
1595 lo = std::sqrt(weightSquared(_curIndex));
1596 hi = lo;
1597 return ;
1598
1599 case None:
1600 lo = 0 ;
1601 hi = 0 ;
1602 return ;
1603 }
1604}
1605
1606
1607// wve adjust for variable bin sizes
1608
1609////////////////////////////////////////////////////////////////////////////////
1610/// Perform boundary safe 'intOrder'-th interpolation of weights in dimension 'dim'
1611/// at current value 'xval'
1612
1613/// \param[in] iDim Index of the histogram dimension along which to interpolate.
1614/// \param[in] xval Value of histogram variable at dimension `iDim` for which
1615/// we want to interpolate the histogram weight.
1616/// \param[in] centralIdx Index of the bin that the point at which we
1617/// interpolate the histogram weight falls into
1618/// (can be obtained with `RooDataHist::calcTreeIndex`).
1619/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1620/// used for the interpolation.
1621/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1622/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1623/// underflow bins are assumed to have weight zero and
1624/// overflow bins have weight one. Otherwise, the
1625/// histogram is mirrored at the boundaries for the
1626/// interpolation.
1628{
1629 auto const& binning = static_cast<RooRealVar&>(*_vars[iDim]).getBinning();
1630
1631 // Fill workspace arrays spanning interpolation area
1632 int fbinC = binning.binNumber(xval) ;
1633 int fbinLo = fbinC-intOrder/2 - ((xval<binning.binCenter(fbinC))?1:0) ;
1634 int fbinM = binning.numBins() ;
1635
1636 auto idxMult = _idxMult[iDim];
1637 auto offsetIdx = centralIdx - idxMult * fbinC;
1638
1639 // Use a class-member buffer to avoid repeated heap allocations.
1640 double * yarr = _interpolationBuffer.data();
1641 double * xarr = yarr + intOrder + 1;
1642
1643 for (int i=fbinLo ; i<=intOrder+fbinLo ; i++) {
1644 int ibin ;
1645 if (i>=0 && i<fbinM) {
1646 // In range
1647 ibin = i ;
1648 xarr[i-fbinLo] = binning.binCenter(ibin) ;
1649 auto idx = offsetIdx + idxMult * ibin;
1650 yarr[i - fbinLo] = _wgt[idx];
1651 if (correctForBinSize) yarr[i-fbinLo] /= _binv[idx] ;
1652 } else if (i>=fbinM) {
1653 // Overflow: mirror
1654 ibin = 2*fbinM-i-1 ;
1655 if (cdfBoundaries) {
1656 xarr[i-fbinLo] = binning.highBound()+1e-10*(i-fbinM+1) ;
1657 yarr[i-fbinLo] = 1.0 ;
1658 } else {
1659 auto idx = offsetIdx + idxMult * ibin;
1660 xarr[i-fbinLo] = 2*binning.highBound()-binning.binCenter(ibin) ;
1661 yarr[i - fbinLo] = _wgt[idx];
1663 yarr[i - fbinLo] /= _binv[idx];
1664 }
1665 } else {
1666 // Underflow: mirror
1667 ibin = -i - 1 ;
1668 if (cdfBoundaries) {
1669 xarr[i-fbinLo] = binning.lowBound()-ibin*(1e-10) ;
1670 yarr[i-fbinLo] = 0.0 ;
1671 } else {
1672 auto idx = offsetIdx + idxMult * ibin;
1673 xarr[i-fbinLo] = 2*binning.lowBound()-binning.binCenter(ibin) ;
1674 yarr[i - fbinLo] = _wgt[idx];
1676 yarr[i - fbinLo] /= _binv[idx];
1677 }
1678 }
1679 }
1681}
1682
1683
1684
1685
1686////////////////////////////////////////////////////////////////////////////////
1687/// Increment the bin content of the bin enclosing the given coordinates.
1688///
1689/// \param[in] row Coordinates of the bin.
1690/// \param[in] wgt Increment by this weight.
1691/// \param[in] sumw2 Optionally, track the sum of squared weights. If a value > 0 or
1692/// a weight != 1. is passed for the first time, a vector for the squared weights will be allocated.
1693void RooDataHist::add(const RooArgSet& row, double wgt, double sumw2)
1694{
1695 checkInit() ;
1696
1697 if ((sumw2 > 0. || wgt != 1.) && !_sumw2) {
1698 // Receiving a weighted entry. SumW2 != sumw from now on.
1699 _sumw2 = new double[_arrSize];
1700 std::copy(_wgt, _wgt+_arrSize, _sumw2);
1701
1703 }
1704
1705 const auto idx = calcTreeIndex(row, false);
1706
1707 _wgt[idx] += wgt ;
1708 if (_sumw2) _sumw2[idx] += (sumw2 > 0 ? sumw2 : wgt*wgt);
1709
1710 _cache_sum_valid = false;
1711}
1712
1713
1714
1715////////////////////////////////////////////////////////////////////////////////
1716/// Set a bin content.
1717/// \param[in] row Coordinates of the bin to be set.
1718/// \param[in] wgt New bin content.
1719/// \param[in] wgtErrLo Low error of the bin content.
1720/// \param[in] wgtErrHi High error of the bin content.
1721void RooDataHist::set(const RooArgSet& row, double wgt, double wgtErrLo, double wgtErrHi)
1722{
1723 checkInit() ;
1724
1726
1727 const auto idx = calcTreeIndex(row, false);
1728
1729 _wgt[idx] = wgt ;
1730 _errLo[idx] = wgtErrLo ;
1731 _errHi[idx] = wgtErrHi ;
1732
1733 _cache_sum_valid = false;
1734}
1735
1736
1737
1738////////////////////////////////////////////////////////////////////////////////
1739/// Set bin content of bin that was last loaded with get(std::size_t).
1740/// \param[in] binNumber Optional bin number to set. If empty, currently active bin is set.
1741/// \param[in] wgt New bin content.
1742/// \param[in] wgtErr Error of the new bin content. If the weight need not have an error, use 0. or a negative number.
1743void RooDataHist::set(std::size_t binNumber, double wgt, double wgtErr) {
1744 checkInit() ;
1745
1746 if (wgtErr > 0. && !_sumw2) {
1747 // Receiving a weighted entry. Need to track sumw2 from now on:
1749
1751 }
1752
1753 _wgt[binNumber] = wgt ;
1754 if (_errLo) _errLo[binNumber] = wgtErr;
1755 if (_errHi) _errHi[binNumber] = wgtErr;
1756 if (_sumw2) _sumw2[binNumber] = wgtErr*wgtErr;
1757
1759}
1760
1761
1762////////////////////////////////////////////////////////////////////////////////
1763/// Set bin content of bin that was last loaded with get(std::size_t).
1764/// \param[in] wgt New bin content.
1765/// \param[in] wgtErr Optional error of the bin content.
1766void RooDataHist::set(double wgt, double wgtErr) {
1767 if (_curIndex == std::numeric_limits<std::size_t>::max()) {
1768 _curIndex = calcTreeIndex(_vars, true) ;
1769 }
1770
1772}
1773
1774
1775////////////////////////////////////////////////////////////////////////////////
1776/// Set a bin content.
1777/// \param[in] row Coordinates to compute the bin from.
1778/// \param[in] wgt New bin content.
1779/// \param[in] wgtErr Optional error of the bin content.
1780void RooDataHist::set(const RooArgSet& row, double wgt, double wgtErr) {
1781 set(calcTreeIndex(row, false), wgt, wgtErr);
1782}
1783
1784
1785
1786////////////////////////////////////////////////////////////////////////////////
1787/// Add all data points contained in 'dset' to this data set with given weight.
1788/// Optional cut string expression selects the data points to be added and can
1789/// reference any variable contained in this data set
1790
1791void RooDataHist::add(const RooAbsData& dset, const char* cut, double wgt)
1792{
1793 RooFormulaVar cutVar("select",cut,*dset.get()) ;
1794 add(dset,&cutVar,wgt) ;
1795}
1796
1797
1798
1799////////////////////////////////////////////////////////////////////////////////
1800/// Add all data points contained in 'dset' to this data set with given weight.
1801/// Optional RooFormulaVar pointer selects the data points to be added.
1802
1804{
1805 checkInit() ;
1806
1807 RooFormulaVar* cloneVar = nullptr;
1808 std::unique_ptr<RooArgSet> tmp;
1809 if (cutVar) {
1810 // Deep clone cutVar and attach clone to this dataset
1811 tmp = std::make_unique<RooArgSet>();
1812 if(RooArgSet(*cutVar).snapshot(*tmp)) {
1813 coutE(DataHandling) << "RooDataHist::add(" << GetName() << ") Couldn't deep-clone cut variable, abort," << std::endl ;
1814 return ;
1815 }
1816
1817 cloneVar = static_cast<RooFormulaVar*>(tmp->find(*cutVar)) ;
1818 cloneVar->attachDataSet(dset) ;
1819 }
1820
1821
1822 Int_t i ;
1823 for (i=0 ; i<dset.numEntries() ; i++) {
1824 const RooArgSet* row = dset.get(i) ;
1825 if (!cloneVar || cloneVar->getVal()) {
1826 add(*row,wgt*dset.weight(), wgt*wgt*dset.weightSquared()) ;
1827 }
1828 }
1829
1831}
1832
1833
1834
1835////////////////////////////////////////////////////////////////////////////////
1836/// Return the sum of the weights of all bins in the histogram.
1837///
1838/// \param[in] correctForBinSize Multiply the sum of weights in each bin
1839/// with the N-dimensional bin volume, making the return value
1840/// the integral over the function represented by this histogram.
1841/// \param[in] inverseBinCor Divide by the N-dimensional bin volume.
1843{
1844 checkInit() ;
1845
1846 // Check if result was cached
1848 if (_cache_sum_valid == static_cast<Int_t>(cache_code)) {
1849 return _cache_sum ;
1850 }
1851
1853 for (Int_t i=0; i < _arrSize; i++) {
1854 const double theBinVolume = correctForBinSize ? (inverseBinCor ? 1/_binv[i] : _binv[i]) : 1.0 ;
1855 kahanSum += _wgt[i] * theBinVolume;
1856 }
1857
1858 // Store result in cache
1860 _cache_sum = kahanSum.Sum();
1861
1862 return kahanSum.Sum();
1863}
1864
1865
1866
1867////////////////////////////////////////////////////////////////////////////////
1868/// Return the sum of the weights of a multi-dimensional slice of the histogram
1869/// by summing only over the dimensions specified in sumSet.
1870///
1871/// The coordinates of all other dimensions are fixed to those given in sliceSet
1872///
1873/// If correctForBinSize is specified, the sum of weights
1874/// is multiplied by the M-dimensional bin volume, (M = N(sumSet)),
1875/// making the return value the integral over the function
1876/// represented by this histogram
1877
1879{
1880 checkInit() ;
1881
1883 varSave.addClone(_vars) ;
1884
1886 sliceOnlySet.remove(sumSet,true,true) ;
1887
1889 std::vector<double> const * pbinv = nullptr;
1890
1893 } else if(correctForBinSize && !inverseBinCor) {
1895 }
1896
1897 // Calculate mask and reference plot bins for non-iterating variables
1898 std::vector<bool> mask(_vars.size());
1899 std::vector<int> refBin(_vars.size());
1900
1901 for (unsigned int i = 0; i < _vars.size(); ++i) {
1902 const RooAbsArg* arg = _vars[i];
1903 const RooAbsLValue* argLv = _lvvars[i]; // Same as above, but cross-cast
1904
1905 if (sumSet.find(*arg)) {
1906 mask[i] = false ;
1907 } else {
1908 mask[i] = true ;
1909 refBin[i] = argLv->getBin();
1910 }
1911 }
1912
1913 // Loop over entire data set, skipping masked entries
1915 for (Int_t ibin=0; ibin < _arrSize; ++ibin) {
1916
1917 std::size_t tmpibin = ibin;
1918 bool skip(false) ;
1919
1920 // Check if this bin belongs in selected slice
1921 for (unsigned int ivar = 0; !skip && ivar < _vars.size(); ++ivar) {
1922 const Int_t idx = tmpibin / _idxMult[ivar] ;
1923 tmpibin -= idx*_idxMult[ivar] ;
1924 if (mask[ivar] && idx!=refBin[ivar])
1925 skip = true ;
1926 }
1927
1928 if (!skip) {
1929 const double theBinVolume = correctForBinSize ? (inverseBinCor ? 1/(*pbinv)[ibin] : (*pbinv)[ibin] ) : 1.0 ;
1931 }
1932 }
1933
1935
1936 return total.Sum();
1937}
1938
1939////////////////////////////////////////////////////////////////////////////////
1940/// Return the sum of the weights of a multi-dimensional slice of the histogram
1941/// by summing only over the dimensions specified in sumSet.
1942///
1943/// The coordinates of all other dimensions are fixed to those given in sliceSet
1944///
1945/// If correctForBinSize is specified, the sum of weights
1946/// is multiplied by the M-dimensional bin volume, (M = N(sumSet)),
1947/// or the fraction of it that falls inside the range rangeName,
1948/// making the return value the integral over the function
1949/// represented by this histogram.
1950///
1951/// If correctForBinSize is not specified, the weights are multiplied by the
1952/// fraction of the bin volume that falls inside the range, i.e. a factor of
1953/// binVolumeInRange/totalBinVolume.
1954
1957 const std::map<const RooAbsArg*, std::pair<double, double> >& ranges,
1958 std::function<double(int)> getBinScale)
1959{
1960 checkInit();
1963 varSave.addClone(_vars);
1964 {
1966 sliceOnlySet.remove(sumSet, true, true);
1968 }
1969
1970 // Calculate mask and reference plot bins for non-iterating variables,
1971 // and get ranges for iterating variables
1972 std::vector<bool> mask(_vars.size());
1973 std::vector<int> refBin(_vars.size());
1974 std::vector<double> rangeLo(_vars.size(), -std::numeric_limits<double>::infinity());
1975 std::vector<double> rangeHi(_vars.size(), +std::numeric_limits<double>::infinity());
1976
1977 for (std::size_t i = 0; i < _vars.size(); ++i) {
1978 const RooAbsArg* arg = _vars[i];
1979 const RooAbsLValue* argLV = _lvvars[i]; // Same object as above, but cross cast
1980
1981 RooAbsArg* sumsetv = sumSet.find(*arg);
1982 RooAbsArg* slicesetv = sliceSet.find(*arg);
1983 mask[i] = !sumsetv;
1984 if (mask[i]) {
1985 assert(argLV);
1986 refBin[i] = argLV->getBin();
1987 }
1988
1989 auto it = ranges.find(sumsetv ? sumsetv : slicesetv);
1990 if (ranges.end() != it) {
1991 rangeLo[i] = it->second.first;
1992 rangeHi[i] = it->second.second;
1993 }
1994 }
1995
1996 // Loop over entire data set, skipping masked entries
1998 for (Int_t ibin = 0; ibin < _arrSize; ++ibin) {
1999 // Check if this bin belongs in selected slice
2000 bool skip{false};
2001 for (int ivar = 0, tmp = ibin; !skip && ivar < int(_vars.size()); ++ivar) {
2002 const Int_t idx = tmp / _idxMult[ivar];
2003 tmp -= idx*_idxMult[ivar];
2004 if (mask[ivar] && idx!=refBin[ivar]) skip = true;
2005 }
2006
2007 if (skip) continue;
2008
2009 // Work out bin volume
2010 // It's not necessary to figure out the bin volume for the slice-only set explicitly here.
2011 // We need to loop over the sumSet anyway to get the partial bin containment correction,
2012 // so we can get the slice-only set volume later by dividing _binv[ibin] / binVolumeSumSetFull.
2013 double binVolumeSumSetFull = 1.;
2014 double binVolumeSumSetInRange = 1.;
2015 for (Int_t ivar = 0, tmp = ibin; ivar < (int)_vars.size(); ++ivar) {
2016 const Int_t idx = tmp / _idxMult[ivar];
2017 tmp -= idx*_idxMult[ivar];
2018
2019 // If the current variable is not in the sumSet, it should not be considered for the bin volume
2020 const auto arg = _vars[ivar];
2021 if (!sumSet.find(*arg)) {
2022 continue;
2023 }
2024
2025 if (_binbounds[ivar].empty()) continue;
2026 const double binLo = _binbounds[ivar][2 * idx];
2027 const double binHi = _binbounds[ivar][2 * idx + 1];
2028 if (binHi < rangeLo[ivar] || binLo > rangeHi[ivar]) {
2029 // bin is outside of allowed range - effective bin volume is zero
2031 break;
2032 }
2033
2035 binVolumeSumSetInRange *= std::min(rangeHi[ivar], binHi) - std::max(rangeLo[ivar], binLo);
2036 }
2038 if (0. == corrPartial) continue;
2040 total += getBinScale(ibin)*(_wgt[ibin] * corr * corrPartial);
2041 }
2042
2044
2045 return total.Sum();
2046}
2047
2048
2049
2050////////////////////////////////////////////////////////////////////////////////
2051/// Fill the transient cache with partial bin volumes with up-to-date
2052/// values for the partial volume specified by observables 'dimSet'
2053
2054const std::vector<double>& RooDataHist::calculatePartialBinVolume(const RooArgSet& dimSet) const
2055{
2056 // The code bitset has all bits set to one whose position corresponds to arguments in dimSet.
2057 // It is used as the key for the bin volume caching hash map.
2058 int code{0};
2059 {
2060 int i{0} ;
2061 for (auto const& v : _vars) {
2062 code += ((dimSet.find(*v) ? 1 : 0) << i) ;
2063 ++i;
2064 }
2065 }
2066
2067 auto& pbinv = _pbinvCache[code];
2068 if(!pbinv.empty()) {
2069 return pbinv;
2070 }
2071 pbinv.resize(_arrSize);
2072
2073 // Calculate plot bins of components from master index
2074 std::vector<bool> selDim(_vars.size());
2075 for (std::size_t i = 0; i < selDim.size(); ++i) {
2076 selDim[i] = (code >> i) & 1 ;
2077 }
2078
2079 // Recalculate partial bin volume cache
2080 for (Int_t ibin=0; ibin < _arrSize ;ibin++) {
2081 Int_t idx(0);
2082 Int_t tmp(ibin);
2083 double theBinVolume(1) ;
2084 for (unsigned int j=0; j < _lvvars.size(); ++j) {
2085 const RooAbsLValue* arg = _lvvars[j];
2086 assert(arg);
2087
2088 idx = tmp / _idxMult[j];
2089 tmp -= idx*_idxMult[j];
2090 if (selDim[j]) {
2091 theBinVolume *= arg->getBinWidth(idx) ;
2092 }
2093 }
2095 }
2096
2097 return pbinv;
2098}
2099
2100
2101////////////////////////////////////////////////////////////////////////////////
2102/// Sum the weights of all bins.
2106
2107
2108
2109////////////////////////////////////////////////////////////////////////////////
2110/// Return the sum of weights in all entries matching cutSpec (if specified)
2111/// and in named range cutRange (if specified)
2112/// Return the
2113
2114double RooDataHist::sumEntries(const char* cutSpec, const char* cutRange) const
2115{
2116 checkInit() ;
2117
2118 if (cutSpec==nullptr && cutRange==nullptr) {
2119 return sumEntries();
2120 } else {
2121
2122 // Setup RooFormulaVar for cutSpec if it is present
2123 std::unique_ptr<RooFormula> select;
2124 if (cutSpec) {
2125 select = std::make_unique<RooFormula>("select",cutSpec,*get());
2126 }
2127
2128 // Otherwise sum the weights in the event
2129 ROOT::Math::KahanSum<> kahanSum;
2130 for (Int_t i=0; i < _arrSize; i++) {
2131 get(i) ;
2132 if ((select && select->eval() == 0.) || (cutRange && !_vars.allInRange(cutRange)))
2133 continue;
2134
2135 kahanSum += weight(i);
2136 }
2137
2138 return kahanSum.Sum();
2139 }
2140}
2141
2142
2143
2144////////////////////////////////////////////////////////////////////////////////
2145/// Reset all bin weights to zero
2146
2148{
2149 // WVE DO NOT CALL RooTreeData::reset() for binned
2150 // datasets as this will delete the bin definitions
2151
2152 std::fill(_wgt, _wgt + _arrSize, 0.);
2153 delete[] _errLo; _errLo = nullptr;
2154 delete[] _errHi; _errHi = nullptr;
2155 delete[] _sumw2; _sumw2 = nullptr;
2156
2158
2159 _cache_sum_valid = false;
2160}
2161
2162
2163
2164////////////////////////////////////////////////////////////////////////////////
2165/// Load bin `binNumber`, and return an argset with the coordinates of the bin centre.
2166/// \note The argset is owned by this data hist, and this function has a side effect, because
2167/// it alters the currently active bin.
2168const RooArgSet* RooDataHist::get(Int_t binNumber) const
2169{
2170 checkInit() ;
2171 _curIndex = binNumber;
2172
2173 return RooAbsData::get(_curIndex);
2174}
2175
2176
2177
2178////////////////////////////////////////////////////////////////////////////////
2179/// Return a RooArgSet with whose coordinates denote the bin centre of the bin
2180/// enclosing the point in `coord`.
2181/// \note The argset is owned by this data hist, and this function has a side effect, because
2182/// it alters the currently active bin.
2184 return get(calcTreeIndex(coord, false));
2185}
2186
2187
2188
2189////////////////////////////////////////////////////////////////////////////////
2190/// Return the volume of the bin enclosing coordinates 'coord'.
2192 checkInit() ;
2193 return _binv[calcTreeIndex(coord, false)] ;
2194}
2195
2196
2197////////////////////////////////////////////////////////////////////////////////
2198/// Create an iterator over all bins in a slice defined by the subset of observables
2199/// listed in sliceArg. The position of the slice is given by otherArgs
2200
2202{
2203 // Update to current position
2205 _curIndex = calcTreeIndex(_vars, true);
2206
2208 if (!intArg) {
2209 coutE(InputArguments) << "RooDataHist::sliceIterator() variable " << sliceArg.GetName() << " is not part of this RooDataHist" << std::endl ;
2210 return nullptr ;
2211 }
2212 return new RooDataHistSliceIter(*this,*intArg) ;
2213}
2214
2215
2216////////////////////////////////////////////////////////////////////////////////
2217/// Change the name of the RooDataHist
2218
2220{
2221 if (_dir) _dir->GetList()->Remove(this);
2222 // We need to use the function from RooAbsData, because it already overrides TNamed::SetName
2224 if (_dir) _dir->GetList()->Add(this);
2225}
2226
2227
2228////////////////////////////////////////////////////////////////////////////////
2229/// Change the title of this RooDataHist
2230
2231void RooDataHist::SetNameTitle(const char *name, const char* title)
2232{
2233 SetName(name);
2234 SetTitle(title);
2235}
2236
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Print value of the dataset, i.e. the sum of weights contained in the dataset
2240
2241void RooDataHist::printValue(ostream& os) const
2242{
2243 os << numEntries() << " bins (" << sumEntries() << " weights)" ;
2244}
2245
2246
2247
2248
2249////////////////////////////////////////////////////////////////////////////////
2250/// Print argument of dataset, i.e. the observable names
2251
2252void RooDataHist::printArgs(ostream& os) const
2253{
2254 os << "[" ;
2255 bool first(true) ;
2256 for (const auto arg : _vars) {
2257 if (first) {
2258 first=false ;
2259 } else {
2260 os << "," ;
2261 }
2262 os << arg->GetName() ;
2263 }
2264 os << "]" ;
2265}
2266
2267
2268
2269////////////////////////////////////////////////////////////////////////////////
2270/// Returns true if dataset contains entries with a non-integer weight.
2271
2273{
2274 for (Int_t i=0; i < _arrSize; ++i) {
2275 const double wgt = _wgt[i];
2276 double intpart;
2277 if (std::abs(std::modf(wgt, &intpart)) > 1.E-10)
2278 return true;
2279 }
2280
2281 return false;
2282}
2283
2284
2285////////////////////////////////////////////////////////////////////////////////
2286/// Print the details on the dataset contents
2287
2288void RooDataHist::printMultiline(ostream& os, Int_t content, bool verbose, TString indent) const
2289{
2291
2292 os << indent << "Binned Dataset " << GetName() << " (" << GetTitle() << ")" << std::endl ;
2293 os << indent << " Contains " << numEntries() << " bins with a total weight of " << sumEntries() << std::endl;
2294
2295 if (!verbose) {
2296 os << indent << " Observables " << _vars << std::endl ;
2297 } else {
2298 os << indent << " Observables: " ;
2300 }
2301
2302 if(verbose) {
2303 if (!_cachedVars.empty()) {
2304 os << indent << " Caches " << _cachedVars << std::endl ;
2305 }
2306 }
2307}
2308
2309/**
2310 * \brief Prints the contents of the RooDataHist to the specified output stream.
2311 *
2312 * This function iterates through all bins of the histogram and prints the
2313 * coordinates of each bin, along with its weight and statistical error.
2314 * It is designed to be robust, handling empty or invalid datasets,
2315 * and works for histograms of any dimension.
2316 *
2317 * \param os The output stream (e.g., std::cout) to write the contents to.
2318 */
2319void RooDataHist::printContents(std::ostream& os) const
2320{
2321 os << "Contents of RooDataHist \"" << GetName() << "\"" << std::endl;
2322
2323 if (numEntries() == 0) {
2324 os << "(dataset is empty)" << std::endl;
2325 return;
2326 }
2327
2328 for (int i = 0; i < numEntries(); ++i) {
2329 const RooArgSet* obs = get(i); // load i-th bin
2330 os << " Bin " << i << ": ";
2331
2332 bool first = true;
2333 for (const auto* var : *obs) {
2334 if (!first) os << ", ";
2335 first = false;
2336
2337 os << var->GetName() << "=";
2338 if (auto realVar = dynamic_cast<const RooRealVar*>(var)) {
2339 os << realVar->getVal();
2340 } else if (auto catVar = dynamic_cast<const RooCategory*>(var)) {
2341 os << catVar->getCurrentLabel();
2342 } else {
2343 os << "(unsupported type)"; //added as a precaution
2344 }
2345 }
2346
2347 double lo, hi;
2349 os << ", weight=" << weight() << " +/- [" << lo << "," << hi << "]"
2350 << std::endl;
2351 }
2352}
2353
2354
2355////////////////////////////////////////////////////////////////////////////////
2356/// Stream an object of class RooDataHist.
2358 if (R__b.IsReading()) {
2359
2360 UInt_t R__s;
2361 UInt_t R__c;
2362 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2363
2364 if (R__v > 2) {
2365 R__b.ReadClassBuffer(RooDataHist::Class(),this,R__v,R__s,R__c);
2366 R__b.CheckByteCount(R__s, R__c, RooDataHist::IsA());
2367 initialize(nullptr, false);
2368 } else {
2369
2370 // Legacy dataset conversion happens here. Legacy RooDataHist inherits from RooTreeData
2371 // which in turn inherits from RooAbsData. Manually stream RooTreeData contents on
2372 // file here and convert it into a RooTreeDataStore which is installed in the
2373 // new-style RooAbsData base class
2374
2375 // --- This is the contents of the streamer code of RooTreeData version 2 ---
2376 UInt_t R__s1;
2377 UInt_t R__c1;
2378 Version_t R__v1 = R__b.ReadVersion(&R__s1, &R__c1); if (R__v1) { }
2379
2381 TTree* X_tree(nullptr) ; R__b >> X_tree;
2382 RooArgSet X_truth ; X_truth.Streamer(R__b);
2384 R__b.CheckByteCount(R__s1, R__c1, TClass::GetClass("RooTreeData"));
2385 // --- End of RooTreeData-v1 streamer
2386
2387 // Construct RooTreeDataStore from X_tree and complete initialization of new-style RooAbsData
2388 _dstore = std::make_unique<RooTreeDataStore>(X_tree,_vars);
2389 _dstore->SetName(GetName()) ;
2390 _dstore->SetTitle(GetTitle()) ;
2391 _dstore->checkInit() ;
2392
2394 R__b >> _arrSize;
2395 delete [] _wgt;
2396 _wgt = new double[_arrSize];
2397 R__b.ReadFastArray(_wgt,_arrSize);
2398 delete [] _errLo;
2399 _errLo = new double[_arrSize];
2400 R__b.ReadFastArray(_errLo,_arrSize);
2401 delete [] _errHi;
2402 _errHi = new double[_arrSize];
2403 R__b.ReadFastArray(_errHi,_arrSize);
2404 delete [] _sumw2;
2405 _sumw2 = new double[_arrSize];
2406 R__b.ReadFastArray(_sumw2,_arrSize);
2407 delete [] _binv;
2408 _binv = new double[_arrSize];
2410 tmpSet.Streamer(R__b);
2411 double tmp;
2412 R__b >> tmp; //_curWeight;
2413 R__b >> tmp; //_curWgtErrLo;
2414 R__b >> tmp; //_curWgtErrHi;
2415 R__b >> tmp; //_curSumW2;
2416 R__b >> tmp; //_curVolume;
2417 R__b >> _curIndex;
2418 R__b.CheckByteCount(R__s, R__c, RooDataHist::IsA());
2419 }
2420
2421 } else {
2422
2423 R__b.WriteClassBuffer(RooDataHist::Class(),this);
2424 }
2425}
2426
2427
2428////////////////////////////////////////////////////////////////////////////////
2429/// Return event weights of all events in range [first, first+len).
2430/// If cacheValidEntries() has been called, out-of-range events will have a weight of 0.
2431std::span<const double> RooDataHist::getWeightBatch(std::size_t first, std::size_t len, bool sumW2 /*=false*/) const {
2432 return {(sumW2 && _sumw2 ? _sumw2 : _wgt) + first, len};
2433}
2434
2435
2436////////////////////////////////////////////////////////////////////////////////
2437/// Hand over pointers to our weight arrays to the data store implementation.
2439 _dstore->setExternalWeightArray(_wgt, _errLo, _errHi, _sumw2);
2440}
2441
2442
2443////////////////////////////////////////////////////////////////////////////////
2444/// Return reference to VarInfo struct with cached histogram variable
2445/// information that is frequently used for histogram weights retrieval.
2446///
2447/// If the `_varInfo` struct was not initialized yet, it will be initialized in
2448/// this function.
2450
2451 if(_varInfo.initialized) return _varInfo;
2452
2453 auto& info = _varInfo;
2454
2455 {
2456 // count the number of real vars and get their indices
2457 info.nRealVars = 0;
2458 size_t iVar = 0;
2459 for (const auto real : _vars) {
2460 if (dynamic_cast<RooRealVar*>(real)) {
2461 if(info.nRealVars == 0) info.realVarIdx1 = iVar;
2462 if(info.nRealVars == 1) info.realVarIdx2 = iVar;
2463 ++info.nRealVars;
2464 }
2465 ++iVar;
2466 }
2467 }
2468
2469 {
2470 // assert that the variables are either real values or categories
2471 for (unsigned int i=0; i < _vars.size(); ++i) {
2472 if (_lvbins[i].get()) {
2473 assert(dynamic_cast<const RooAbsReal*>(_vars[i]));
2474 } else {
2475 assert(dynamic_cast<const RooAbsCategoryLValue*>(_vars[i]));
2476 }
2477 }
2478 }
2479
2480 info.initialized = true;
2481
2482 return info;
2483}
#define e(i)
Definition RSha256.hxx:103
#define coutI(a)
#define coutE(a)
#define TRACE_DESTROY
Definition RooTrace.h:24
#define TRACE_CREATE
Definition RooTrace.h:23
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
static unsigned int total
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 mask
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 offset
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 x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:110
float xmin
#define hi
float * q
float ymin
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Definition Util.h:141
static KahanSum< T, N > Accumulate(Iterator begin, Iterator end, T initialValue=T{})
Iterate over a range and return an instance of a KahanSum.
Definition Util.h:230
const_iterator begin() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
void attachDataSet(const RooAbsData &set)
Replace server nodes with names matching the dataset variable names with those data set variables,...
Abstract base class for RooRealVar binning definitions.
int binNumber(double x) const
Returns the bin number corresponding to the value x.
virtual void binNumbers(double const *x, int *bins, std::size_t n, int coef=1) const =0
Compute the bin indices for multiple values of x.
virtual bool isUniform() const
virtual double highBound() const =0
virtual double lowBound() const =0
virtual std::string translateBinNumber(RooFit::Experimental::CodegenContext &ctx, RooAbsArg const &var, int coef) const
virtual RooAbsBinning * clone(const char *name=nullptr) const =0
Abstract base class for objects that represent a discrete value that can be set from the outside,...
bool hasLabel(const std::string &label) const
Check if a state with name label exists.
Abstract container object that can hold multiple RooAbsArg objects.
RooAbsCollection & assignValueOnly(const RooAbsCollection &other, bool forceIfSizeOne=false)
Sets the value of any argument in our set that also appears in the other set.
bool allInRange(const char *rangeSpec) const
Return true if all contained object report to have their value inside the specified range.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
Storage_t::size_type size() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:56
virtual const RooArgSet * get() const
Definition RooAbsData.h:100
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.
void setGlobalObservables(RooArgSet const &globalObservables)
Sets the global observables stored in this data.
void checkInit() const
static StorageType defaultStorageType
Definition RooAbsData.h:298
std::unique_ptr< RooAbsDataStore > _dstore
Data storage implementation.
Definition RooAbsData.h:358
virtual void fill()
RooArgSet _vars
Dimensions of this data set.
Definition RooAbsData.h:355
RooArgSet _cachedVars
! External variables cached with this data set
Definition RooAbsData.h:356
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
void Streamer(TBuffer &) override
Stream an object of class RooAbsData.
virtual RooPlot * plotOnImpl(RooPlot *frame, PlotOpt o) const
Create and fill a histogram of the frame's variable and append it to the frame.
Abstract base class for objects that are lvalues, i.e.
virtual double getBinWidth(Int_t i, const char *rangeName=nullptr) const =0
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:159
RooArgSet * selectCommon(const RooAbsCollection &refColl) const
Use RooAbsCollection::selecCommon(), but return as RooArgSet.
Definition RooArgSet.h:154
Object to represent discrete states.
Definition RooCategory.h:28
bool defineType(const std::string &label)
Define a state with given name.
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
Configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
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'.
void defineDependency(const char *refArgName, const char *neededArgName)
Define that processing argument name refArgName requires processing of argument named neededArgName t...
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...
RooArgSet * getSet(const char *name, RooArgSet *set=nullptr) const
Return RooArgSet property registered with name 'name'.
bool defineSet(const char *name, const char *argName, int setNum, const RooArgSet *set=nullptr)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
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...
const RooLinkedList & getObjectList(const char *name) const
Return list of objects registered with name 'name'.
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
std::span< const double > getWeightBatch(std::size_t first, std::size_t len, bool sumW2=false) const override
Return event weights of all events in range [first, first+len).
void interpolateQuadratic(double *output, std::span< const double > xVals, bool correctForBinSize, bool cdfBoundaries)
A vectorized version of interpolateDim for boundary safe quadratic interpolation of one dimensional h...
double sum(bool correctForBinSize, bool inverseCorr=false) const
Return the sum of the weights of all bins in the histogram.
void weights(double *output, std::span< double const > xVals, int intOrder, bool correctForBinSize, bool cdfBoundaries)
A vectorized version of RooDataHist::weight() for one dimensional histograms with up to one dimension...
Int_t _cache_sum_valid
! Is cache sum valid? Needs to be Int_t instead of CacheSumState_t for subclasses.
void printContents(std::ostream &os=std::cout) const override
Print the contents of the dataset to the specified output stream.
double interpolateDim(int iDim, double xval, size_t centralIdx, int intOrder, bool correctForBinSize, bool cdfBoundaries)
Perform boundary safe 'intOrder'-th interpolation of weights in dimension 'dim' at current value 'xva...
double weightSquared() const override
Return squared weight of last bin that was requested with get().
friend class RooDataHistSliceIter
void importTH1(const RooArgList &vars, const TH1 &histo, double initWgt, bool doDensityCorrection)
Import data from given TH1/2/3 into this RooDataHist.
static TClass * Class()
TClass * IsA() const override
void SetNameTitle(const char *name, const char *title) override
Change the title of this RooDataHist.
double _cache_sum
! Cache for sum of entries ;
void initialize(const char *binningName=nullptr, bool fillTree=true)
Initialization procedure: allocate weights array, calculate multipliers needed for N-space to 1-dim a...
VarInfo _varInfo
!
std::string declWeightArrayForCodeSquash(RooFit::Experimental::CodegenContext &ctx, bool correctForBinSize) const
Int_t getIndex(const RooAbsCollection &coord, bool fast=false) const
Calculate bin number of the given coordinates.
void add(const RooArgSet &row, double wgt=1.0) override
Add wgt to the bin content enclosed by the coordinates passed in row.
Definition RooDataHist.h:72
const std::vector< double > & calculatePartialBinVolume(const RooArgSet &dimSet) const
Fill the transient cache with partial bin volumes with up-to-date values for the partial volume speci...
static std::unique_ptr< RooAbsDataStore > makeDefaultDataStore(RooStringView name, RooStringView title, RooArgSet const &vars)
double weightInterpolated(const RooArgSet &bin, int intOrder, bool correctForBinSize, bool cdfBoundaries)
Return the weight at given coordinates with interpolation.
std::unordered_map< int, std::vector< double > > _pbinvCache
! Cache for arrays of partial bin volumes
void checkBinBounds() const
void initializeAsymErrArrays() const
void set(std::size_t binNumber, double weight, double wgtErr)
Set bin content of bin that was last loaded with get(std::size_t).
void weightError(double &lo, double &hi, ErrorType etype=Poisson) const override
Return the asymmetric errors on the current weight.
double * _errHi
[_arrSize] High-side error on weight array
void importTH1Set(const RooArgList &vars, RooCategory &indexCat, std::map< std::string, TH1 * > hmap, double initWgt, bool doDensityCorrection)
Import data from given set of TH1/2/3 into this RooDataHist.
void adjustBinning(const RooArgList &vars, const TH1 &href, Int_t *offset=nullptr)
Adjust binning specification on first and optionally second and third observable to binning in given ...
double * _binv
[_arrSize] Bin volume array
RooDataHist()
Default constructor.
ULong64_t _curIndex
Current index.
std::string calculateTreeIndexForCodeSquash(RooFit::Experimental::CodegenContext &ctx, const RooAbsCollection &coords, bool reverse=false) const
double weightFast(const RooArgSet &bin, int intOrder, bool correctForBinSize, bool cdfBoundaries)
A faster version of RooDataHist::weight that assumes the passed arguments are aligned with the histog...
double weight() const override
Return weight of last bin that was requested with get().
std::vector< std::vector< double > > _binbounds
! list of bin bounds per dimension
void printArgs(std::ostream &os) const override
Print argument of dataset, i.e. the observable names.
void importDHistSet(const RooArgList &vars, RooCategory &indexCat, std::map< std::string, RooDataHist * > dmap, double initWgt)
Import data from given set of TH1/2/3 into this RooDataHist.
void _adjustBinning(RooRealVar &theirVar, const TAxis &axis, RooRealVar *ourVar, Int_t *offset)
Helper doing the actual work of adjustBinning().
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Print the details on the dataset contents.
double * _sumw2
[_arrSize] Sum of weights^2
TIterator * sliceIterator(RooAbsArg &sliceArg, const RooArgSet &otherArgs)
Create an iterator over all bins in a slice defined by the subset of observables listed in sliceArg.
Int_t calcTreeIndex() const
Legacy overload to calculate the tree index from the current value of _vars.
~RooDataHist() override
Destructor.
bool isNonPoissonWeighted() const override
Returns true if dataset contains entries with a non-integer weight.
std::vector< RooAbsLValue * > _lvvars
! List of observables casted as RooAbsLValue
void SetName(const char *name) override
Change the name of the RooDataHist.
std::vector< std::unique_ptr< const RooAbsBinning > > _lvbins
! List of used binnings associated with lvalues
void Streamer(TBuffer &) override
Stream an object of class RooDataHist.
std::vector< double > _interpolationBuffer
! Buffer to contain values used for weight interpolation
std::vector< Int_t > _idxMult
void registerWeightArraysToDataStore() const
Hand over pointers to our weight arrays to the data store implementation.
void reset() override
Reset all bin weights to zero.
double * _errLo
[_arrSize] Low-side error on weight array
double * _wgt
[_arrSize] Weight array
RooPlot * plotOnImpl(RooPlot *frame, PlotOpt o) const override
Back end function to plotting functionality.
void printValue(std::ostream &os) const override
Print value of the dataset, i.e. the sum of weights contained in the dataset.
VarInfo const & getVarInfo()
Return reference to VarInfo struct with cached histogram variable information that is frequently used...
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()) const override
Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods.
const RooArgSet * get() const override
Get bin centre of current bin.
Definition RooDataHist.h:82
void interpolateLinear(double *output, std::span< const double > xVals, bool correctForBinSize, bool cdfBoundaries)
A vectorized version of interpolateDim for boundary safe linear interpolation of one dimensional hist...
double binVolume() const
Return volume of current bin.
double sumEntries() const override
Sum the weights of all bins.
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
A class to maintain the context for squashing of RooFit models into code.
std::string buildArg(RooAbsCollection const &x, std::string const &arrayType="double")
Function to save a RooListProxy as an array in the squashed code.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
static const RooHistError & instance()
Return a reference to a singleton object that is created the first time this method is called.
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
static double interpolate(double yArr[], Int_t nOrder, double x)
Definition RooMath.cxx:78
Plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:43
RooAbsRealLValue * getPlotVar() const
Definition RooPlot.h:137
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
Variable that can be changed from the outside.
Definition RooRealVar.h:37
The RooStringView is a wrapper around a C-style string that can also be constructed from a std::strin...
Class to manage histogram axis.
Definition TAxis.h:32
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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:2973
virtual TList * GetList() const
Definition TDirectory.h:223
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9176
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Int_t GetDimension() const
Definition TH1.h:527
TAxis * GetXaxis()
Definition TH1.h:571
virtual Int_t GetNbinsX() const
Definition TH1.h:541
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5122
Iterator abstract base class.
Definition TIterator.h:30
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
Basic string class.
Definition TString.h:138
A TTree represents a columnar dataset.
Definition TTree.h:89
const Int_t n
Definition legend1.C:16
TH1F * h1
Definition legend1.C:5
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
RooAbsBinning * bins
Definition RooAbsData.h:313
Structure to cache information on the histogram variable that is frequently used for histogram weight...
TLine l
Definition textangle.C:4
static void output()