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(i) * 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 // If the variable has no binning explicitly set (the default for a
802 // freshly-constructed RooRealVar, which reports zero bins), materialize the
803 // historical default binning. _vars holds this dataset's own clones (see
804 // RooAbsData::initializeVars, which addClone's the input variables), so this
805 // does not affect the user's original variable.
806 if (RooRealVar* rrv = dynamic_cast<RooRealVar*>(_vars[i])) {
807 if (rrv->getBins() == 0) {
808 rrv->setBinning(RooUniformBinning(rrv->getMin(), rrv->getMax(), RooAbsRealLValue::DefaultNBins));
809 }
810 }
811
812 auto lvarg = dynamic_cast<RooAbsLValue*>(_vars[i]);
813 assert(lvarg);
814 _lvvars.push_back(lvarg);
815
816 const RooAbsBinning* binning = lvarg->getBinningPtr(nullptr);
817 _lvbins.emplace_back(binning ? binning->clone() : nullptr);
818 }
819
820
821 // Allocate coefficients array
822 _idxMult.resize(_vars.size()) ;
823
824 _arrSize = 1 ;
825 unsigned int n = 0u;
826 for (const auto var : _vars) {
827 auto arg = dynamic_cast<const RooAbsLValue*>(var);
828 assert(arg);
829
830 // Calculate sub-index multipliers for master index
831 for (unsigned int i = 0u; i<n; i++) {
832 _idxMult[i] *= arg->numBins() ;
833 }
834 _idxMult[n++] = 1 ;
835
836 // Calculate dimension of weight array
837 _arrSize *= arg->numBins() ;
838 }
839
840 // Allocate and initialize weight array if necessary
841 if (!_wgt) {
842 initArray(_wgt, _arrSize, 0.);
843 delete[] _errLo; _errLo = nullptr;
844 delete[] _errHi; _errHi = nullptr;
845 delete[] _sumw2; _sumw2 = nullptr;
847
848 // Refill array pointers in data store when reading
849 // from Streamer
850 if (!fillTree) {
852 }
853 }
854
855 if (!fillTree) return ;
856
857 // Fill TTree with bin center coordinates
858 // Calculate plot bins of components from master index
859
860 for (Int_t ibin=0 ; ibin < _arrSize ; ibin++) {
861 Int_t j(0);
862 Int_t idx(0);
863 Int_t tmp(ibin);
864 double theBinVolume(1) ;
865 for (auto arg2 : _lvvars) {
866 idx = tmp / _idxMult[j] ;
867 tmp -= idx*_idxMult[j++] ;
868 arg2->setBin(idx) ;
869 theBinVolume *= arg2->getBinWidth(idx) ;
870 }
872
873 fill() ;
874 }
875
876
877}
878
879
880////////////////////////////////////////////////////////////////////////////////
881
883{
884 if (!_binbounds.empty()) return;
885 for (auto& it : _lvbins) {
886 _binbounds.push_back(std::vector<double>());
887 if (it) {
888 std::vector<double>& bounds = _binbounds.back();
889 bounds.reserve(2 * it->numBins());
890 for (Int_t i = 0; i < it->numBins(); ++i) {
891 bounds.push_back(it->binLow(i));
892 bounds.push_back(it->binHigh(i));
893 }
894 }
895 }
896}
897
898
899////////////////////////////////////////////////////////////////////////////////
900/// Copy constructor
901
903 RooAbsData(other,newname), RooDirItem(), _arrSize(other._arrSize), _idxMult(other._idxMult), _pbinvCache(other._pbinvCache)
904{
905 // Allocate and initialize weight array
906 assert(_arrSize == other._arrSize);
907 cloneArray(_wgt, other._wgt, other._arrSize);
908 cloneArray(_errLo, other._errLo, other._arrSize);
909 cloneArray(_errHi, other._errHi, other._arrSize);
910 cloneArray(_binv, other._binv, other._arrSize);
911 cloneArray(_sumw2, other._sumw2, other._arrSize);
912
913 // Fill array of LValue pointers to variables
914 for (const auto rvarg : _vars) {
915 auto lvarg = dynamic_cast<RooAbsLValue*>(rvarg);
916 assert(lvarg);
917 _lvvars.push_back(lvarg);
918 const RooAbsBinning* binning = lvarg->getBinningPtr(nullptr);
919 _lvbins.emplace_back(binning ? binning->clone() : nullptr) ;
920 }
921
923}
924
925
926////////////////////////////////////////////////////////////////////////////////
927/// Implementation of RooAbsData virtual method that drives the RooAbsData::reduce() methods
928
929std::unique_ptr<RooAbsData> RooDataHist::reduceEng(const RooArgSet& varSubset, const RooFormulaVar* cutVar, const char* cutRange,
930 std::size_t nStart, std::size_t nStop) const
931{
932 checkInit() ;
935 auto rdh = std::make_unique<RooDataHist>(GetName(), GetTitle(), myVarSubset);
936
937 RooFormulaVar* cloneVar = nullptr;
938 std::unique_ptr<RooArgSet> tmp;
939 if (cutVar) {
940 tmp = std::make_unique<RooArgSet>();
941 // Deep clone cutVar and attach clone to this dataset
942 if (RooArgSet(*cutVar).snapshot(*tmp)) {
943 coutE(DataHandling) << "RooDataHist::reduceEng(" << GetName() << ") Couldn't deep-clone cut variable, abort," << std::endl ;
944 return nullptr;
945 }
946 cloneVar = static_cast<RooFormulaVar*>(tmp->find(*cutVar));
947 cloneVar->attachDataSet(*this) ;
948 }
949
950 double lo;
951 double hi;
952 const std::size_t nevt = nStop < static_cast<std::size_t>(numEntries()) ? nStop : static_cast<std::size_t>(numEntries());
953 for (auto i=nStart; i<nevt ; i++) {
954 const RooArgSet* row = get(i) ;
955
956 bool doSelect(true) ;
957 if (cutRange) {
958 for (const auto arg : *row) {
959 if (!arg->inRange(cutRange)) {
960 doSelect = false ;
961 break ;
962 }
963 }
964 }
965 if (!doSelect) continue ;
966
967 if (!cloneVar || cloneVar->getVal()) {
968 weightError(lo,hi,SumW2) ;
969 rdh->add(*row,weight(i),lo*lo) ;
970 }
971 }
972
973 return rdh ;
974}
975
976
977
978////////////////////////////////////////////////////////////////////////////////
979/// Destructor
980
982{
983 delete[] _wgt;
984 delete[] _errLo;
985 delete[] _errHi;
986 delete[] _sumw2;
987 delete[] _binv;
988
989 removeFromDir(this) ;
991}
992
993
994
995
996////////////////////////////////////////////////////////////////////////////////
997/// Calculate bin number of the given coordinates. If only a subset of the internal
998/// coordinates are passed, the missing coordinates are taken at their current value.
999/// \param[in] coord Variables that are representing the coordinates.
1000/// \param[in] fast If the variables in `coord` and the ones of the data hist have the
1001/// same size and layout, `fast` can be set to skip checking that all variables are
1002/// present in `coord`.
1004 checkInit() ;
1005 return calcTreeIndex(coord, fast);
1006}
1007
1009 bool correctForBinSize) const
1010{
1011 std::vector<double> vals(_arrSize);
1012 for (std::size_t i = 0; i < vals.size(); ++i) {
1013 vals[i] = correctForBinSize ? _wgt[i] / _binv[i] : _wgt[i];
1014 }
1015 return ctx.buildArg(vals);
1016}
1017
1019 const RooAbsCollection &coords, bool reverse) const
1020{
1021 assert(coords.size() == _vars.size());
1022
1023 std::string code;
1024 int idxMult = 1;
1025
1026 for (std::size_t i = 0; i < _vars.size(); ++i) {
1027
1028 std::size_t iVar = reverse ? _vars.size() - 1 - i : i;
1029 const RooAbsArg *internalVar = _vars[iVar];
1030 const RooAbsArg *theVar = coords[iVar];
1031
1032 const RooAbsBinning *binning = _lvbins[iVar].get();
1033 if (!binning) {
1034 coutE(InputArguments) << "RooHistPdf::weight(" << GetName()
1035 << ") ERROR: Code Squashing currently does not support category values." << std::endl;
1036 return "";
1037 }
1038
1039 if (i > 0)
1040 code += " + ";
1041 code += binning->translateBinNumber(ctx, *theVar, idxMult);
1042
1043 // Use RooAbsLValue here because it also generalized to categories, which
1044 // is useful in the future. dynamic_cast because it's a cross-cast.
1045 idxMult *= dynamic_cast<RooAbsLValue const *>(internalVar)->numBins();
1046 }
1047
1048 return _vars.size() == 1 ? code : "(" + code + ")";
1049}
1050
1051////////////////////////////////////////////////////////////////////////////////
1052/// Calculate the bin index corresponding to the coordinates passed as argument.
1053/// \param[in] coords Coordinates. If `fast == false`, these can be partial.
1054/// \param[in] fast Promise that the coordinates in `coords` have the same order
1055/// as the internal coordinates. In this case, values are looked up only by index.
1056std::size_t RooDataHist::calcTreeIndex(const RooAbsCollection& coords, bool fast) const
1057{
1058 // With fast, caller promises that layout of `coords` is identical to our internal `vars`.
1059 // Previously, this was verified with an assert in debug mode like this:
1060 //
1061 // assert(!fast || coords.hasSameLayout(_vars));
1062 //
1063 // However, there are usecases where the externally provided `coords` have
1064 // different names than the internal variables, even though they correspond
1065 // to each other. For example, if the observables in the computation graph
1066 // are renamed with `redirectServers`. Hence, we can't do a meaningful assert
1067 // here.
1068
1069 if (&_vars == &coords)
1070 fast = true;
1071
1072 std::size_t masterIdx = 0;
1073
1074 for (unsigned int i=0; i < _vars.size(); ++i) {
1075 const RooAbsArg* internalVar = _vars[i];
1076 const RooAbsBinning* binning = _lvbins[i].get();
1077
1078 // Find the variable that we need values from.
1079 // That's either the variable directly from the external coordinates
1080 // or we find the external one that has the same name as "internalVar".
1081 const RooAbsArg* theVar = fast ? coords[i] : coords.find(*internalVar);
1082 if (!theVar) {
1083 // Variable is not in external coordinates. Use current internal value.
1085 }
1086 // If fast is on, users promise that the sets have the same layout:
1087 //
1088 // assert(!fast || strcmp(internalVar->GetName(), theVar->GetName()) == 0);
1089 //
1090 // This assert is commented out for the same reasons that applied to the
1091 // other assert explained above.
1092
1093 if (binning) {
1094 assert(dynamic_cast<const RooAbsReal*>(theVar));
1095 const double val = static_cast<const RooAbsReal*>(theVar)->getVal();
1096 masterIdx += _idxMult[i] * binning->binNumber(val);
1097 } else {
1098 // We are a category. No binning.
1099 assert(dynamic_cast<const RooAbsCategoryLValue*>(theVar));
1100 auto cat = static_cast<const RooAbsCategoryLValue*>(theVar);
1101 masterIdx += _idxMult[i] * cat->getBin(static_cast<const char*>(nullptr));
1102 }
1103 }
1104
1105 return masterIdx ;
1106}
1107
1108
1109////////////////////////////////////////////////////////////////////////////////
1110/// Back end function to plotting functionality. Plot RooDataHist on given
1111/// frame in mode specified by plot options 'o'. The main purpose of
1112/// this function is to match the specified binning on 'o' to the
1113/// internal binning of the plot observable in this RooDataHist.
1114/// \note see RooAbsData::plotOnImpl() for plotting options.
1116{
1117 checkInit() ;
1118 if (o.bins) return RooAbsData::plotOnImpl(frame,o) ;
1119
1120 if(!frame) {
1121 coutE(InputArguments) << ClassName() << "::" << GetName() << ":plotOn: frame is null" << std::endl;
1122 return nullptr;
1123 }
1124 auto var= static_cast<RooAbsRealLValue*>(frame->getPlotVar());
1125 if(!var) {
1126 coutE(InputArguments) << ClassName() << "::" << GetName()
1127 << ":plotOn: frame does not specify a plot variable" << std::endl;
1128 return nullptr;
1129 }
1130
1131 auto dataVar = static_cast<RooRealVar*>(_vars.find(*var));
1132 if (!dataVar) {
1133 coutE(InputArguments) << ClassName() << "::" << GetName()
1134 << ":plotOn: dataset doesn't contain plot frame variable" << std::endl;
1135 return nullptr;
1136 }
1137
1138 o.bins = &dataVar->getBinning() ;
1139 return RooAbsData::plotOnImpl(frame,o) ;
1140}
1141
1142
1143////////////////////////////////////////////////////////////////////////////////
1144/// A vectorized version of interpolateDim for boundary safe quadratic
1145/// interpolation of one dimensional histograms.
1146///
1147/// \param[out] output An array of interpolated weights corresponding to the
1148/// values in xVals.
1149/// \param[in] xVals An array of event coordinates for which the weights should be
1150/// calculated.
1151/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1152/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1153/// Underflow bins are assumed to have weight zero and
1154/// overflow bins have weight one. Otherwise, the
1155/// histogram is mirrored at the boundaries for the
1156/// interpolation.
1157
1158void RooDataHist::interpolateQuadratic(double* output, std::span<const double> xVals,
1160{
1161 const std::size_t nBins = numEntries();
1162 const std::size_t nEvents = xVals.size();
1163
1164 RooAbsBinning const& binning = *_lvbins[0];
1165 // Reuse the output buffer for bin indices and zero-initialize it
1166 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1167 std::fill(binIndices, binIndices + nEvents, 0);
1168 binning.binNumbers(xVals.data(), binIndices, nEvents);
1169
1170 // Extend coordinates and weights with one extra point before the first bin
1171 // and one extra point after the last bin. This means the original histogram
1172 // bins span elements 1 to nBins in coordsExt and weightsExt
1173 std::vector<double> coordsExt(nBins+3);
1174 double* binCoords = coordsExt.data() + 2;
1175 binCoords[0] = binning.lowBound() + 0.5*_binv[0];
1176 for (std::size_t binIdx = 1; binIdx < nBins ; ++binIdx) {
1177 if (binning.isUniform()) {
1178 double binWidth = _binv[0];
1179 binCoords[binIdx] = binIdx*binWidth + binCoords[0];
1180 }
1181 else {
1182 double binCentDiff = 0.5*_binv[binIdx-1] + 0.5*_binv[binIdx];
1184 }
1185 }
1186
1187 std::vector<double> weightsExt(nBins+3);
1188 // Fill weights for bins that are inside histogram boundaries
1189 for (std::size_t binIdx = 0; binIdx < nBins; ++binIdx) {
1191 }
1192
1193 if (cdfBoundaries) {
1194 coordsExt[0] = - 1e-10 + binning.lowBound();
1195 weightsExt[0] = 0.;
1196
1197 coordsExt[1] = binning.lowBound();
1198 weightsExt[1] = 0.;
1199
1200 coordsExt[nBins+2] = binning.highBound();
1201 weightsExt[nBins+2] = 1.;
1202 }
1203 else {
1204 // Mirror first two bins and last bin
1205 coordsExt[0] = binCoords[1] - 2*_binv[0] - _binv[1];
1206 weightsExt[0] = weightsExt[3];
1207
1208 coordsExt[1] = binCoords[0] - _binv[0];
1209 weightsExt[1] = weightsExt[2];
1210
1211 coordsExt[nBins+2] = binCoords[nBins-1] + _binv[nBins-1];
1212 weightsExt[nBins+2] = weightsExt[nBins+1];
1213 }
1214
1215 // We use the current bin center and two bin centers on the left for
1216 // interpolation if xVal is to the left of the current bin center
1217 for (std::size_t i = 0; i < nEvents ; ++i) {
1218 double xVal = xVals[i];
1219 std::size_t binIdx = binIndices[i] + 2;
1220
1221 // If xVal is to the right of the current bin center, shift all bin
1222 // coordinates one step to the right and use that for the interpolation
1223 if (xVal > coordsExt[binIdx]) {
1224 binIdx += 1;
1225 }
1226
1227 double x1 = coordsExt[binIdx-2];
1228 double y1 = weightsExt[binIdx-2];
1229
1230 double x2 = coordsExt[binIdx-1];
1231 double y2 = weightsExt[binIdx-1];
1232
1233 double x3 = coordsExt[binIdx];
1234 double y3 = weightsExt[binIdx];
1235
1236 // Evaluate a few repeated factors
1237 double quotient = (x3-x1) / (x2-x1);
1238 double x1Sqrd = x1*x1;
1239 double x3Sqrd = x3*x3;
1240 // Solve coefficients in system of three quadratic equations!
1241 double secondCoeff = (y3 - y1 - (y2-y1) * quotient) / (x3Sqrd - x1Sqrd - (x2*x2 - x1Sqrd) * quotient);
1242 double firstCoeff = (y3 - y1 - secondCoeff*(x3Sqrd - x1Sqrd)) / (x3-x1);
1244 // Get the interpolated weight using the equation of a second degree polynomial
1245 output[i] = secondCoeff * xVal * xVal + firstCoeff * xVal + zerothCoeff;
1246 }
1247}
1248
1249
1250////////////////////////////////////////////////////////////////////////////////
1251/// A vectorized version of interpolateDim for boundary safe linear
1252/// interpolation of one dimensional histograms.
1253///
1254/// \param[out] output An array of interpolated weights corresponding to the
1255/// values in xVals.
1256/// \param[in] xVals An array of event coordinates for which the weights should be
1257/// calculated.
1258/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1259/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1260/// Underflow bins are assumed to have weight zero and
1261/// overflow bins have weight one. Otherwise, the
1262/// histogram is mirrored at the boundaries for the
1263/// interpolation.
1264
1265void RooDataHist::interpolateLinear(double* output, std::span<const double> xVals,
1267{
1268 const std::size_t nBins = numEntries();
1269 const std::size_t nEvents = xVals.size();
1270
1271 RooAbsBinning const& binning = *_lvbins[0];
1272 // Reuse the output buffer for bin indices and zero-initialize it
1273 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1274 std::fill(binIndices, binIndices + nEvents, 0);
1275 binning.binNumbers(xVals.data(), binIndices, nEvents);
1276
1277 // Extend coordinates and weights with one extra point before the first bin
1278 // and one extra point after the last bin. This means the original histogram
1279 // bins span elements 1 to nBins in coordsExt and weightsExt
1280 std::vector<double> coordsExt(nBins+2);
1281 double* binCoords = coordsExt.data() + 1;
1282 binCoords[0] = binning.lowBound() + 0.5*_binv[0];
1283 for (std::size_t binIdx = 1; binIdx < nBins ; ++binIdx) {
1284 if (binning.isUniform()) {
1285 double binWidth = _binv[0];
1286 binCoords[binIdx] = binIdx*binWidth + binCoords[0];
1287 }
1288 else {
1289 double binCentDiff = 0.5*_binv[binIdx-1] + 0.5*_binv[binIdx];
1291 }
1292 }
1293
1294 std::vector<double> weightsExt(nBins+2);
1295 // Fill weights for bins that are inside histogram boundaries
1296 for (std::size_t binIdx = 0; binIdx < nBins; ++binIdx) {
1298 }
1299
1300 // Fill weights for bins that are outside histogram boundaries
1301 if (cdfBoundaries) {
1302 coordsExt[0] = binning.lowBound();
1303 weightsExt[0] = 0.;
1304 coordsExt[nBins+1] = binning.highBound();
1305 weightsExt[nBins+1] = 1.;
1306 }
1307 else {
1308 // Mirror first and last bins
1309 coordsExt[0] = binCoords[0] - _binv[0];
1310 weightsExt[0] = weightsExt[1];
1311 coordsExt[nBins+1] = binCoords[nBins-1] + _binv[nBins-1];
1312 weightsExt[nBins+1] = weightsExt[nBins];
1313 }
1314
1315 // Interpolate between current bin center and one bin center to the left
1316 // if xVal is to the left of the current bin center
1317 for (std::size_t i = 0; i < nEvents ; ++i) {
1318 double xVal = xVals[i];
1319 std::size_t binIdx = binIndices[i] + 1;
1320
1321 // If xVal is to the right of the current bin center, interpolate between
1322 // current bin center and one bin center to the right instead
1323 if (xVal > coordsExt[binIdx]) { binIdx += 1; }
1324
1325 double x1 = coordsExt[binIdx-1];
1326 double y1 = weightsExt[binIdx-1];
1327 double x2 = coordsExt[binIdx];
1328 double y2 = weightsExt[binIdx];
1329
1330 // Find coefficients by solving a system of two linear equations
1331 double firstCoeff = (y2-y1) / (x2-x1);
1332 double zerothCoeff = y1 - firstCoeff * x1;
1333 // Get the interpolated weight using the equation of a straight line
1334 output[i] = firstCoeff * xVal + zerothCoeff;
1335 }
1336}
1337
1338
1339////////////////////////////////////////////////////////////////////////////////
1340/// A vectorized version of RooDataHist::weight() for one dimensional histograms
1341/// with up to one dimensional interpolation.
1342/// \param[out] output An array of weights corresponding the values in xVals.
1343/// \param[in] xVals An array of coordinates for which the weights should be
1344/// calculated.
1345/// \param[in] intOrder Interpolation order; 0th and 1st order are supported.
1346/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1347/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1348/// Underflow bins are assumed to have weight zero and
1349/// overflow bins have weight one. Otherwise, the
1350/// histogram is mirrored at the boundaries for the
1351/// interpolation.
1352
1353void RooDataHist::weights(double* output, std::span<double const> xVals, int intOrder, bool correctForBinSize, bool cdfBoundaries)
1354{
1355 auto const nEvents = xVals.size();
1356
1357 if (intOrder == 0) {
1358 RooAbsBinning const& binning = *_lvbins[0];
1359
1360 // Reuse the output buffer for bin indices and zero-initialize it
1361 auto binIndices = reinterpret_cast<int*>(output + nEvents) - nEvents;
1362 std::fill(binIndices, binIndices + nEvents, 0);
1363 binning.binNumbers(xVals.data(), binIndices, nEvents);
1364
1365 for (std::size_t i=0; i < nEvents; ++i) {
1366 auto binIdx = binIndices[i];
1367 output[i] = correctForBinSize ? _wgt[binIdx] / _binv[binIdx] : _wgt[binIdx];
1368 }
1369 }
1370 else if (intOrder == 1) {
1372 }
1373 else if (intOrder == 2) {
1375 }
1376 else {
1377 // Higher dimensional scenarios not yet implemented
1378 coutE(InputArguments) << "RooDataHist::weights(" << GetName() << ") interpolation in "
1379 << intOrder << " dimensions not yet implemented" << std::endl ;
1380 // Fall back to 1st order interpolation
1382 }
1383}
1384
1385
1386////////////////////////////////////////////////////////////////////////////////
1387/// A faster version of RooDataHist::weight that assumes the passed arguments
1388/// are aligned with the histogram variables.
1389/// \param[in] bin Coordinates for which the weight should be calculated.
1390/// Has to be aligned with the internal histogram variables.
1391/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1392/// used for the interpolation. If zero, the bare weight for
1393/// the bin enclosing the coordinatesis returned.
1394/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1395/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1396/// underflow bins are assumed to have weight zero and
1397/// overflow bins have weight one. Otherwise, the
1398/// histogram is mirrored at the boundaries for the
1399/// interpolation.
1400
1402{
1403 checkInit() ;
1404
1405 // Handle illegal intOrder values
1406 if (intOrder<0) {
1407 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") ERROR: interpolation order must be positive" << std::endl ;
1408 return 0 ;
1409 }
1410
1411 // Handle no-interpolation case
1412 if (intOrder==0) {
1413 const auto idx = calcTreeIndex(bin, true);
1414 return correctForBinSize ? _wgt[idx] / _binv[idx] : _wgt[idx];
1415 }
1416
1417 // Handle all interpolation cases
1419}
1420
1421
1422////////////////////////////////////////////////////////////////////////////////
1423/// Return the weight at given coordinates with optional interpolation.
1424/// \param[in] bin Coordinates for which the weight should be calculated.
1425/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1426/// used for the interpolation. If zero, the bare weight for
1427/// the bin enclosing the coordinatesis returned.
1428/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1429/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1430/// underflow bins are assumed to have weight zero and
1431/// overflow bins have weight one. Otherwise, the
1432/// histogram is mirrored at the boundaries for the
1433/// interpolation.
1434/// \param[in] oneSafe Ignored.
1435
1437{
1438 checkInit() ;
1439
1440 // Handle illegal intOrder values
1441 if (intOrder<0) {
1442 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") ERROR: interpolation order must be positive" << std::endl ;
1443 return 0 ;
1444 }
1445
1446 // Handle no-interpolation case
1447 if (intOrder==0) {
1448 const auto idx = calcTreeIndex(bin, false);
1449 return correctForBinSize ? _wgt[idx] / _binv[idx] : _wgt[idx];
1450 }
1451
1452 // Handle all interpolation cases
1454
1456}
1457
1458
1459////////////////////////////////////////////////////////////////////////////////
1460/// Return the weight at given coordinates with interpolation.
1461/// \param[in] bin Coordinates for which the weight should be calculated.
1462/// Has to be aligned with the internal histogram variables.
1463/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1464/// used for the interpolation.
1465/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1466/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1467/// underflow bins are assumed to have weight zero and
1468/// overflow bins have weight one. Otherwise, the
1469/// histogram is mirrored at the boundaries for the
1470/// interpolation.
1471
1473 VarInfo const& varInfo = getVarInfo();
1474
1475 const auto centralIdx = calcTreeIndex(bin, true);
1476
1477 double wInt{0} ;
1478 if (varInfo.nRealVars == 1) {
1479
1480 // buffer needs to be 2 x (interpolation order + 1), with the factor 2 for x and y.
1481 _interpolationBuffer.resize(2 * intOrder + 2);
1482
1483 // 1-dimensional interpolation
1484 auto const& realX = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx1]);
1486
1487 } else if (varInfo.nRealVars == 2) {
1488
1489 // buffer needs to be 2 x 2 x (interpolation order + 1), with one factor 2
1490 // for x and y, and the other for the number of dimensions.
1491 _interpolationBuffer.resize(4 * intOrder + 4);
1492
1493 // 2-dimensional interpolation
1494 auto const& realX = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx1]);
1495 auto const& realY = static_cast<RooRealVar const&>(*bin[varInfo.realVarIdx2]);
1496 double xval = realX.getVal() ;
1497 double yval = realY.getVal() ;
1498
1499 // Use the internal binning of the y variable, not the binning of the
1500 // variable passed in `bin`. The latter may be a different object than the
1501 // one owned by this RooDataHist (e.g. the histogram observable clone of a
1502 // RooHistPdf), with an unrelated default binning. The bin indexing below
1503 // relies on `_idxMult` and `centralIdx`, which are both expressed in terms
1504 // of the internal binning, so the y binning must match it too. This mirrors
1505 // what calcTreeIndex() and interpolateDim() do for the other dimensions.
1506 RooAbsBinning const& binningY = static_cast<RooRealVar const&>(*_vars[varInfo.realVarIdx2]).getBinning();
1507
1508 int ybinC = binningY.binNumber(yval) ;
1509 int ybinLo = ybinC-intOrder/2 - ((yval<binningY.binCenter(ybinC))?1:0) ;
1510 int ybinM = binningY.numBins() ;
1511
1512 auto idxMultY = _idxMult[varInfo.realVarIdx2];
1514
1515 // Use a class-member buffer to avoid repeated heap allocations.
1516 double * yarr = _interpolationBuffer.data() + 2 * intOrder + 2; // add offset to skip part reserved for other dim
1517 double * xarr = yarr + intOrder + 1;
1518 for (int i=ybinLo ; i<=intOrder+ybinLo ; i++) {
1519 int ibin ;
1520 if (i>=0 && i<ybinM) {
1521 // In range
1522 ibin = i ;
1523 xarr[i-ybinLo] = binningY.binCenter(ibin) ;
1524 } else if (i>=ybinM) {
1525 // Overflow: mirror
1526 ibin = 2*ybinM-i-1 ;
1527 xarr[i-ybinLo] = 2*binningY.highBound()-binningY.binCenter(ibin) ;
1528 } else {
1529 // Underflow: mirror
1530 ibin = -i -1;
1531 xarr[i-ybinLo] = 2*binningY.lowBound()-binningY.binCenter(ibin) ;
1532 }
1535 }
1536
1537 if (gDebug>7) {
1538 std::cout << "RooDataHist interpolating data is" << std::endl ;
1539 std::cout << "xarr = " ;
1540 for (int q=0; q<=intOrder ; q++) std::cout << xarr[q] << " " ;
1541 std::cout << " yarr = " ;
1542 for (int q=0; q<=intOrder ; q++) std::cout << yarr[q] << " " ;
1543 std::cout << std::endl ;
1544 }
1546
1547 } else {
1548
1549 // Higher dimensional scenarios not yet implemented
1550 coutE(InputArguments) << "RooDataHist::weight(" << GetName() << ") interpolation in "
1551 << varInfo.nRealVars << " dimensions not yet implemented" << std::endl ;
1553
1554 }
1555
1556 return wInt ;
1557}
1558
1559
1561 if (!_errLo || !_errHi) {
1562 initArray(_errLo, _arrSize, -1.);
1563 initArray(_errHi, _arrSize, -1.);
1565 }
1566}
1567
1568
1569////////////////////////////////////////////////////////////////////////////////
1570/// Return the asymmetric errors on the current weight.
1571/// \note see weightError(ErrorType) const for symmetric error.
1572/// \param[out] lo Low error.
1573/// \param[out] hi High error.
1574/// \param[in] etype Type of error to compute. May throw if not supported.
1575/// Supported errors are
1576/// - `Poisson` Default. Asymmetric Poisson errors (68% CL).
1577/// - `SumW2` The square root of the sum of weights. (Symmetric).
1578/// - `None` Return zero.
1579void RooDataHist::weightError(double& lo, double& hi, ErrorType etype) const
1580{
1581 checkInit() ;
1582
1583 switch (etype) {
1584
1585 case Auto:
1586 throw std::invalid_argument("RooDataHist::weightError(" + std::string(GetName()) + ") error type Auto not allowed here");
1587 break ;
1588
1589 case Expected:
1590 throw std::invalid_argument("RooDataHist::weightError(" + std::string(GetName()) + ") error type Expected not allowed here");
1591 break ;
1592
1593 case Poisson: {
1594 if (_errLo && _errLo[_curIndex] >= 0.0) {
1595 // Weight is preset or precalculated
1596 lo = _errLo[_curIndex];
1597 hi = _errHi[_curIndex];
1598 return ;
1599 }
1600
1601 // We didn't track asymmetric errors so far, so now we need to allocate
1603
1604 // Calculate poisson errors
1605 double ym;
1606 double yp;
1607 const double w = weight(_curIndex);
1608 RooHistError::instance().getPoissonInterval(Int_t(w+0.5),ym,yp,1) ;
1609 _errLo[_curIndex] = w-ym;
1610 _errHi[_curIndex] = yp-w;
1611 lo = _errLo[_curIndex];
1612 hi = _errHi[_curIndex];
1613 return ;
1614 }
1615
1616 case SumW2:
1617 lo = std::sqrt(weightSquared(_curIndex));
1618 hi = lo;
1619 return ;
1620
1621 case None:
1622 lo = 0 ;
1623 hi = 0 ;
1624 return ;
1625 }
1626}
1627
1628
1629// wve adjust for variable bin sizes
1630
1631////////////////////////////////////////////////////////////////////////////////
1632/// Perform boundary safe 'intOrder'-th interpolation of weights in dimension 'dim'
1633/// at current value 'xval'
1634
1635/// \param[in] iDim Index of the histogram dimension along which to interpolate.
1636/// \param[in] xval Value of histogram variable at dimension `iDim` for which
1637/// we want to interpolate the histogram weight.
1638/// \param[in] centralIdx Index of the bin that the point at which we
1639/// interpolate the histogram weight falls into
1640/// (can be obtained with `RooDataHist::calcTreeIndex`).
1641/// \param[in] intOrder Interpolation order, i.e. how many neighbouring bins are
1642/// used for the interpolation.
1643/// \param[in] correctForBinSize Enable the inverse bin volume correction factor.
1644/// \param[in] cdfBoundaries Enable the special boundary condition for a cdf:
1645/// underflow bins are assumed to have weight zero and
1646/// overflow bins have weight one. Otherwise, the
1647/// histogram is mirrored at the boundaries for the
1648/// interpolation.
1650{
1651 auto const& binning = static_cast<RooRealVar&>(*_vars[iDim]).getBinning();
1652
1653 // Fill workspace arrays spanning interpolation area
1654 int fbinC = binning.binNumber(xval) ;
1655 int fbinLo = fbinC-intOrder/2 - ((xval<binning.binCenter(fbinC))?1:0) ;
1656 int fbinM = binning.numBins() ;
1657
1658 auto idxMult = _idxMult[iDim];
1659 auto offsetIdx = centralIdx - idxMult * fbinC;
1660
1661 // Use a class-member buffer to avoid repeated heap allocations.
1662 double * yarr = _interpolationBuffer.data();
1663 double * xarr = yarr + intOrder + 1;
1664
1665 for (int i=fbinLo ; i<=intOrder+fbinLo ; i++) {
1666 int ibin ;
1667 if (i>=0 && i<fbinM) {
1668 // In range
1669 ibin = i ;
1670 xarr[i-fbinLo] = binning.binCenter(ibin) ;
1671 auto idx = offsetIdx + idxMult * ibin;
1672 yarr[i - fbinLo] = _wgt[idx];
1673 if (correctForBinSize) yarr[i-fbinLo] /= _binv[idx] ;
1674 } else if (i>=fbinM) {
1675 // Overflow: mirror
1676 ibin = 2*fbinM-i-1 ;
1677 if (cdfBoundaries) {
1678 xarr[i-fbinLo] = binning.highBound()+1e-10*(i-fbinM+1) ;
1679 yarr[i-fbinLo] = 1.0 ;
1680 } else {
1681 auto idx = offsetIdx + idxMult * ibin;
1682 xarr[i-fbinLo] = 2*binning.highBound()-binning.binCenter(ibin) ;
1683 yarr[i - fbinLo] = _wgt[idx];
1685 yarr[i - fbinLo] /= _binv[idx];
1686 }
1687 } else {
1688 // Underflow: mirror
1689 ibin = -i - 1 ;
1690 if (cdfBoundaries) {
1691 xarr[i-fbinLo] = binning.lowBound()-ibin*(1e-10) ;
1692 yarr[i-fbinLo] = 0.0 ;
1693 } else {
1694 auto idx = offsetIdx + idxMult * ibin;
1695 xarr[i-fbinLo] = 2*binning.lowBound()-binning.binCenter(ibin) ;
1696 yarr[i - fbinLo] = _wgt[idx];
1698 yarr[i - fbinLo] /= _binv[idx];
1699 }
1700 }
1701 }
1703}
1704
1705
1706
1707
1708////////////////////////////////////////////////////////////////////////////////
1709/// Increment the bin content of the bin enclosing the given coordinates.
1710///
1711/// \param[in] row Coordinates of the bin.
1712/// \param[in] wgt Increment by this weight.
1713/// \param[in] sumw2 Optionally, track the sum of squared weights. If a value > 0 or
1714/// a weight != 1. is passed for the first time, a vector for the squared weights will be allocated.
1715void RooDataHist::add(const RooArgSet& row, double wgt, double sumw2)
1716{
1717 checkInit() ;
1718
1719 if ((sumw2 > 0. || wgt != 1.) && !_sumw2) {
1720 // Receiving a weighted entry. SumW2 != sumw from now on.
1721 _sumw2 = new double[_arrSize];
1722 std::copy(_wgt, _wgt+_arrSize, _sumw2);
1723
1725 }
1726
1727 const auto idx = calcTreeIndex(row, false);
1728
1729 _wgt[idx] += wgt ;
1730 if (_sumw2) _sumw2[idx] += (sumw2 > 0 ? sumw2 : wgt*wgt);
1731
1732 _cache_sum_valid = false;
1733}
1734
1735
1736
1737////////////////////////////////////////////////////////////////////////////////
1738/// Set a bin content.
1739/// \param[in] row Coordinates of the bin to be set.
1740/// \param[in] wgt New bin content.
1741/// \param[in] wgtErrLo Low error of the bin content.
1742/// \param[in] wgtErrHi High error of the bin content.
1743void RooDataHist::set(const RooArgSet& row, double wgt, double wgtErrLo, double wgtErrHi)
1744{
1745 checkInit() ;
1746
1748
1749 const auto idx = calcTreeIndex(row, false);
1750
1751 _wgt[idx] = wgt ;
1752 _errLo[idx] = wgtErrLo ;
1753 _errHi[idx] = wgtErrHi ;
1754
1755 _cache_sum_valid = false;
1756}
1757
1758
1759
1760////////////////////////////////////////////////////////////////////////////////
1761/// Set bin content of bin that was last loaded with get(std::size_t).
1762/// \param[in] binNumber Optional bin number to set. If empty, currently active bin is set.
1763/// \param[in] wgt New bin content.
1764/// \param[in] wgtErr Error of the new bin content. If the weight need not have an error, use 0. or a negative number.
1765void RooDataHist::set(std::size_t binNumber, double wgt, double wgtErr) {
1766 checkInit() ;
1767
1768 if (wgtErr > 0. && !_sumw2) {
1769 // Receiving a weighted entry. Need to track sumw2 from now on:
1771
1773 }
1774
1775 _wgt[binNumber] = wgt ;
1776 if (_errLo) _errLo[binNumber] = wgtErr;
1777 if (_errHi) _errHi[binNumber] = wgtErr;
1778 if (_sumw2) _sumw2[binNumber] = wgtErr*wgtErr;
1779
1781}
1782
1783
1784////////////////////////////////////////////////////////////////////////////////
1785/// Set bin content of bin that was last loaded with get(std::size_t).
1786/// \param[in] wgt New bin content.
1787/// \param[in] wgtErr Optional error of the bin content.
1788void RooDataHist::set(double wgt, double wgtErr) {
1789 if (_curIndex == std::numeric_limits<std::size_t>::max()) {
1790 _curIndex = calcTreeIndex(_vars, true) ;
1791 }
1792
1794}
1795
1796
1797////////////////////////////////////////////////////////////////////////////////
1798/// Set a bin content.
1799/// \param[in] row Coordinates to compute the bin from.
1800/// \param[in] wgt New bin content.
1801/// \param[in] wgtErr Optional error of the bin content.
1802void RooDataHist::set(const RooArgSet& row, double wgt, double wgtErr) {
1803 set(calcTreeIndex(row, false), wgt, wgtErr);
1804}
1805
1806
1807
1808////////////////////////////////////////////////////////////////////////////////
1809/// Add all data points contained in 'dset' to this data set with given weight.
1810/// Optional cut string expression selects the data points to be added and can
1811/// reference any variable contained in this data set
1812
1813void RooDataHist::add(const RooAbsData& dset, const char* cut, double wgt)
1814{
1815 RooFormulaVar cutVar("select",cut,*dset.get()) ;
1816 add(dset,&cutVar,wgt) ;
1817}
1818
1819
1820
1821////////////////////////////////////////////////////////////////////////////////
1822/// Add all data points contained in 'dset' to this data set with given weight.
1823/// Optional RooFormulaVar pointer selects the data points to be added.
1824
1826{
1827 checkInit() ;
1828
1829 RooFormulaVar* cloneVar = nullptr;
1830 std::unique_ptr<RooArgSet> tmp;
1831 if (cutVar) {
1832 // Deep clone cutVar and attach clone to this dataset
1833 tmp = std::make_unique<RooArgSet>();
1834 if(RooArgSet(*cutVar).snapshot(*tmp)) {
1835 coutE(DataHandling) << "RooDataHist::add(" << GetName() << ") Couldn't deep-clone cut variable, abort," << std::endl ;
1836 return ;
1837 }
1838
1839 cloneVar = static_cast<RooFormulaVar*>(tmp->find(*cutVar)) ;
1840 cloneVar->attachDataSet(dset) ;
1841 }
1842
1843
1844 Int_t i ;
1845 for (i=0 ; i<dset.numEntries() ; i++) {
1846 const RooArgSet* row = dset.get(i) ;
1847 if (!cloneVar || cloneVar->getVal()) {
1848 add(*row,wgt*dset.weight(), wgt*wgt*dset.weightSquared()) ;
1849 }
1850 }
1851
1853}
1854
1855
1856
1857////////////////////////////////////////////////////////////////////////////////
1858/// Return the sum of the weights of all bins in the histogram.
1859///
1860/// \param[in] correctForBinSize Multiply the sum of weights in each bin
1861/// with the N-dimensional bin volume, making the return value
1862/// the integral over the function represented by this histogram.
1863/// \param[in] inverseBinCor Divide by the N-dimensional bin volume.
1865{
1866 checkInit() ;
1867
1868 // Check if result was cached
1870 if (_cache_sum_valid == static_cast<Int_t>(cache_code)) {
1871 return _cache_sum ;
1872 }
1873
1875 for (Int_t i=0; i < _arrSize; i++) {
1876 const double theBinVolume = correctForBinSize ? (inverseBinCor ? 1/_binv[i] : _binv[i]) : 1.0 ;
1877 kahanSum += _wgt[i] * theBinVolume;
1878 }
1879
1880 // Store result in cache
1882 _cache_sum = kahanSum.Sum();
1883
1884 return kahanSum.Sum();
1885}
1886
1887
1888
1889////////////////////////////////////////////////////////////////////////////////
1890/// Return the sum of the weights of a multi-dimensional slice of the histogram
1891/// by summing only over the dimensions specified in sumSet.
1892///
1893/// The coordinates of all other dimensions are fixed to those given in sliceSet
1894///
1895/// If correctForBinSize is specified, the sum of weights
1896/// is multiplied by the M-dimensional bin volume, (M = N(sumSet)),
1897/// making the return value the integral over the function
1898/// represented by this histogram
1899
1901{
1902 checkInit() ;
1903
1905 varSave.addClone(_vars) ;
1906
1908 sliceOnlySet.remove(sumSet,true,true) ;
1909
1911 std::vector<double> const * pbinv = nullptr;
1912
1915 } else if(correctForBinSize && !inverseBinCor) {
1917 }
1918
1919 // Calculate mask and reference plot bins for non-iterating variables
1920 std::vector<bool> mask(_vars.size());
1921 std::vector<int> refBin(_vars.size());
1922
1923 for (unsigned int i = 0; i < _vars.size(); ++i) {
1924 const RooAbsArg* arg = _vars[i];
1925 const RooAbsLValue* argLv = _lvvars[i]; // Same as above, but cross-cast
1926
1927 if (sumSet.find(*arg)) {
1928 mask[i] = false ;
1929 } else {
1930 mask[i] = true ;
1931 refBin[i] = argLv->getBin();
1932 }
1933 }
1934
1935 // Loop over entire data set, skipping masked entries
1937 for (Int_t ibin=0; ibin < _arrSize; ++ibin) {
1938
1939 std::size_t tmpibin = ibin;
1940 bool skip(false) ;
1941
1942 // Check if this bin belongs in selected slice
1943 for (unsigned int ivar = 0; !skip && ivar < _vars.size(); ++ivar) {
1944 const Int_t idx = tmpibin / _idxMult[ivar] ;
1945 tmpibin -= idx*_idxMult[ivar] ;
1946 if (mask[ivar] && idx!=refBin[ivar])
1947 skip = true ;
1948 }
1949
1950 if (!skip) {
1951 const double theBinVolume = correctForBinSize ? (inverseBinCor ? 1/(*pbinv)[ibin] : (*pbinv)[ibin] ) : 1.0 ;
1953 }
1954 }
1955
1957
1958 return total.Sum();
1959}
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Return the sum of the weights of a multi-dimensional slice of the histogram
1963/// by summing only over the dimensions specified in sumSet.
1964///
1965/// The coordinates of all other dimensions are fixed to those given in sliceSet
1966///
1967/// If correctForBinSize is specified, the sum of weights
1968/// is multiplied by the M-dimensional bin volume, (M = N(sumSet)),
1969/// or the fraction of it that falls inside the range rangeName,
1970/// making the return value the integral over the function
1971/// represented by this histogram.
1972///
1973/// If correctForBinSize is not specified, the weights are multiplied by the
1974/// fraction of the bin volume that falls inside the range, i.e. a factor of
1975/// binVolumeInRange/totalBinVolume.
1976
1979 const std::map<const RooAbsArg*, std::pair<double, double> >& ranges,
1980 std::function<double(int)> getBinScale)
1981{
1982 checkInit();
1985 varSave.addClone(_vars);
1986 {
1988 sliceOnlySet.remove(sumSet, true, true);
1990 }
1991
1992 // Calculate mask and reference plot bins for non-iterating variables,
1993 // and get ranges for iterating variables
1994 std::vector<bool> mask(_vars.size());
1995 std::vector<int> refBin(_vars.size());
1996 std::vector<double> rangeLo(_vars.size(), -std::numeric_limits<double>::infinity());
1997 std::vector<double> rangeHi(_vars.size(), +std::numeric_limits<double>::infinity());
1998
1999 for (std::size_t i = 0; i < _vars.size(); ++i) {
2000 const RooAbsArg* arg = _vars[i];
2001 const RooAbsLValue* argLV = _lvvars[i]; // Same object as above, but cross cast
2002
2003 RooAbsArg* sumsetv = sumSet.find(*arg);
2004 RooAbsArg* slicesetv = sliceSet.find(*arg);
2005 mask[i] = !sumsetv;
2006 if (mask[i]) {
2007 assert(argLV);
2008 refBin[i] = argLV->getBin();
2009 }
2010
2011 auto it = ranges.find(sumsetv ? sumsetv : slicesetv);
2012 if (ranges.end() != it) {
2013 rangeLo[i] = it->second.first;
2014 rangeHi[i] = it->second.second;
2015 }
2016 }
2017
2018 // Loop over entire data set, skipping masked entries
2020 for (Int_t ibin = 0; ibin < _arrSize; ++ibin) {
2021 // Check if this bin belongs in selected slice
2022 bool skip{false};
2023 for (int ivar = 0, tmp = ibin; !skip && ivar < int(_vars.size()); ++ivar) {
2024 const Int_t idx = tmp / _idxMult[ivar];
2025 tmp -= idx*_idxMult[ivar];
2026 if (mask[ivar] && idx!=refBin[ivar]) skip = true;
2027 }
2028
2029 if (skip) continue;
2030
2031 // Work out bin volume
2032 // It's not necessary to figure out the bin volume for the slice-only set explicitly here.
2033 // We need to loop over the sumSet anyway to get the partial bin containment correction,
2034 // so we can get the slice-only set volume later by dividing _binv[ibin] / binVolumeSumSetFull.
2035 double binVolumeSumSetFull = 1.;
2036 double binVolumeSumSetInRange = 1.;
2037 for (Int_t ivar = 0, tmp = ibin; ivar < (int)_vars.size(); ++ivar) {
2038 const Int_t idx = tmp / _idxMult[ivar];
2039 tmp -= idx*_idxMult[ivar];
2040
2041 // If the current variable is not in the sumSet, it should not be considered for the bin volume
2042 const auto arg = _vars[ivar];
2043 if (!sumSet.find(*arg)) {
2044 continue;
2045 }
2046
2047 if (_binbounds[ivar].empty()) continue;
2048 const double binLo = _binbounds[ivar][2 * idx];
2049 const double binHi = _binbounds[ivar][2 * idx + 1];
2050 if (binHi < rangeLo[ivar] || binLo > rangeHi[ivar]) {
2051 // bin is outside of allowed range - effective bin volume is zero
2053 break;
2054 }
2055
2057 binVolumeSumSetInRange *= std::min(rangeHi[ivar], binHi) - std::max(rangeLo[ivar], binLo);
2058 }
2060 if (0. == corrPartial) continue;
2062 total += getBinScale(ibin)*(_wgt[ibin] * corr * corrPartial);
2063 }
2064
2066
2067 return total.Sum();
2068}
2069
2070
2071
2072////////////////////////////////////////////////////////////////////////////////
2073/// Fill the transient cache with partial bin volumes with up-to-date
2074/// values for the partial volume specified by observables 'dimSet'
2075
2076const std::vector<double>& RooDataHist::calculatePartialBinVolume(const RooArgSet& dimSet) const
2077{
2078 // The code bitset has all bits set to one whose position corresponds to arguments in dimSet.
2079 // It is used as the key for the bin volume caching hash map.
2080 int code{0};
2081 {
2082 int i{0} ;
2083 for (auto const& v : _vars) {
2084 code += ((dimSet.find(*v) ? 1 : 0) << i) ;
2085 ++i;
2086 }
2087 }
2088
2089 auto& pbinv = _pbinvCache[code];
2090 if(!pbinv.empty()) {
2091 return pbinv;
2092 }
2093 pbinv.resize(_arrSize);
2094
2095 // Calculate plot bins of components from master index
2096 std::vector<bool> selDim(_vars.size());
2097 for (std::size_t i = 0; i < selDim.size(); ++i) {
2098 selDim[i] = (code >> i) & 1 ;
2099 }
2100
2101 // Recalculate partial bin volume cache
2102 for (Int_t ibin=0; ibin < _arrSize ;ibin++) {
2103 Int_t idx(0);
2104 Int_t tmp(ibin);
2105 double theBinVolume(1) ;
2106 for (unsigned int j=0; j < _lvvars.size(); ++j) {
2107 const RooAbsLValue* arg = _lvvars[j];
2108 assert(arg);
2109
2110 idx = tmp / _idxMult[j];
2111 tmp -= idx*_idxMult[j];
2112 if (selDim[j]) {
2113 theBinVolume *= arg->getBinWidth(idx) ;
2114 }
2115 }
2117 }
2118
2119 return pbinv;
2120}
2121
2122
2123////////////////////////////////////////////////////////////////////////////////
2124/// Sum the weights of all bins.
2128
2129
2130
2131////////////////////////////////////////////////////////////////////////////////
2132/// Return the sum of weights in all entries matching cutSpec (if specified)
2133/// and in named range cutRange (if specified)
2134/// Return the
2135
2136double RooDataHist::sumEntries(const char* cutSpec, const char* cutRange) const
2137{
2138 checkInit() ;
2139
2140 if (cutSpec==nullptr && cutRange==nullptr) {
2141 return sumEntries();
2142 } else {
2143
2144 // Setup RooFormulaVar for cutSpec if it is present
2145 std::unique_ptr<RooFormula> select;
2146 if (cutSpec) {
2147 select = std::make_unique<RooFormula>("select",cutSpec,*get());
2148 }
2149
2150 // Otherwise sum the weights in the event
2151 ROOT::Math::KahanSum<> kahanSum;
2152 for (Int_t i=0; i < _arrSize; i++) {
2153 get(i) ;
2154 if ((select && select->eval() == 0.) || (cutRange && !_vars.allInRange(cutRange)))
2155 continue;
2156
2157 kahanSum += weight(i);
2158 }
2159
2160 return kahanSum.Sum();
2161 }
2162}
2163
2164
2165
2166////////////////////////////////////////////////////////////////////////////////
2167/// Reset all bin weights to zero
2168
2170{
2171 // WVE DO NOT CALL RooTreeData::reset() for binned
2172 // datasets as this will delete the bin definitions
2173
2174 std::fill(_wgt, _wgt + _arrSize, 0.);
2175 delete[] _errLo; _errLo = nullptr;
2176 delete[] _errHi; _errHi = nullptr;
2177 delete[] _sumw2; _sumw2 = nullptr;
2178
2180
2181 _cache_sum_valid = false;
2182}
2183
2184
2185
2186////////////////////////////////////////////////////////////////////////////////
2187/// Load bin `binNumber`, and return an argset with the coordinates of the bin centre.
2188/// \note The argset is owned by this data hist, and this function has a side effect, because
2189/// it alters the currently active bin.
2190const RooArgSet* RooDataHist::get(Int_t binNumber) const
2191{
2192 checkInit() ;
2193 _curIndex = binNumber;
2194
2195 return RooAbsData::get(_curIndex);
2196}
2197
2198
2199
2200////////////////////////////////////////////////////////////////////////////////
2201/// Return a RooArgSet with whose coordinates denote the bin centre of the bin
2202/// enclosing the point in `coord`.
2203/// \note The argset is owned by this data hist, and this function has a side effect, because
2204/// it alters the currently active bin.
2206 return get(calcTreeIndex(coord, false));
2207}
2208
2209
2210
2211////////////////////////////////////////////////////////////////////////////////
2212/// Return the volume of the bin enclosing coordinates 'coord'.
2214 checkInit() ;
2215 return _binv[calcTreeIndex(coord, false)] ;
2216}
2217
2218
2219////////////////////////////////////////////////////////////////////////////////
2220/// Create an iterator over all bins in a slice defined by the subset of observables
2221/// listed in sliceArg. The position of the slice is given by otherArgs
2222
2224{
2225 // Update to current position
2227 _curIndex = calcTreeIndex(_vars, true);
2228
2230 if (!intArg) {
2231 coutE(InputArguments) << "RooDataHist::sliceIterator() variable " << sliceArg.GetName() << " is not part of this RooDataHist" << std::endl ;
2232 return nullptr ;
2233 }
2234 return new RooDataHistSliceIter(*this,*intArg) ;
2235}
2236
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Change the name of the RooDataHist
2240
2242{
2243 if (_dir) _dir->GetList()->Remove(this);
2244 // We need to use the function from RooAbsData, because it already overrides TNamed::SetName
2246 if (_dir) _dir->GetList()->Add(this);
2247}
2248
2249
2250////////////////////////////////////////////////////////////////////////////////
2251/// Change the title of this RooDataHist
2252
2253void RooDataHist::SetNameTitle(const char *name, const char* title)
2254{
2255 SetName(name);
2256 SetTitle(title);
2257}
2258
2259
2260////////////////////////////////////////////////////////////////////////////////
2261/// Print value of the dataset, i.e. the sum of weights contained in the dataset
2262
2263void RooDataHist::printValue(ostream& os) const
2264{
2265 os << numEntries() << " bins (" << sumEntries() << " weights)" ;
2266}
2267
2268
2269
2270
2271////////////////////////////////////////////////////////////////////////////////
2272/// Print argument of dataset, i.e. the observable names
2273
2274void RooDataHist::printArgs(ostream& os) const
2275{
2276 os << "[" ;
2277 bool first(true) ;
2278 for (const auto arg : _vars) {
2279 if (first) {
2280 first=false ;
2281 } else {
2282 os << "," ;
2283 }
2284 os << arg->GetName() ;
2285 }
2286 os << "]" ;
2287}
2288
2289
2290
2291////////////////////////////////////////////////////////////////////////////////
2292/// Returns true if dataset contains entries with a non-integer weight.
2293
2295{
2296 for (Int_t i=0; i < _arrSize; ++i) {
2297 const double wgt = _wgt[i];
2298 double intpart;
2299 if (std::abs(std::modf(wgt, &intpart)) > 1.E-10)
2300 return true;
2301 }
2302
2303 return false;
2304}
2305
2306
2307////////////////////////////////////////////////////////////////////////////////
2308/// Print the details on the dataset contents
2309
2310void RooDataHist::printMultiline(ostream& os, Int_t content, bool verbose, TString indent) const
2311{
2313
2314 os << indent << "Binned Dataset " << GetName() << " (" << GetTitle() << ")" << std::endl ;
2315 os << indent << " Contains " << numEntries() << " bins with a total weight of " << sumEntries() << std::endl;
2316
2317 if (!verbose) {
2318 os << indent << " Observables " << _vars << std::endl ;
2319 } else {
2320 os << indent << " Observables: " ;
2322 }
2323
2324 if(verbose) {
2325 if (!_cachedVars.empty()) {
2326 os << indent << " Caches " << _cachedVars << std::endl ;
2327 }
2328 }
2329}
2330
2331/**
2332 * \brief Prints the contents of the RooDataHist to the specified output stream.
2333 *
2334 * This function iterates through all bins of the histogram and prints the
2335 * coordinates of each bin, along with its weight and statistical error.
2336 * It is designed to be robust, handling empty or invalid datasets,
2337 * and works for histograms of any dimension.
2338 *
2339 * \param os The output stream (e.g., std::cout) to write the contents to.
2340 */
2341void RooDataHist::printContents(std::ostream& os) const
2342{
2343 os << "Contents of RooDataHist \"" << GetName() << "\"" << std::endl;
2344
2345 if (numEntries() == 0) {
2346 os << "(dataset is empty)" << std::endl;
2347 return;
2348 }
2349
2350 for (int i = 0; i < numEntries(); ++i) {
2351 const RooArgSet* obs = get(i); // load i-th bin
2352 os << " Bin " << i << ": ";
2353
2354 bool first = true;
2355 for (const auto* var : *obs) {
2356 if (!first) os << ", ";
2357 first = false;
2358
2359 os << var->GetName() << "=";
2360 if (auto realVar = dynamic_cast<const RooRealVar*>(var)) {
2361 os << realVar->getVal();
2362 } else if (auto catVar = dynamic_cast<const RooCategory*>(var)) {
2363 os << catVar->getCurrentLabel();
2364 } else {
2365 os << "(unsupported type)"; //added as a precaution
2366 }
2367 }
2368
2369 double lo, hi;
2371 os << ", weight=" << weight(i) << " +/- [" << lo << "," << hi << "]"
2372 << std::endl;
2373 }
2374}
2375
2376
2377////////////////////////////////////////////////////////////////////////////////
2378/// Stream an object of class RooDataHist.
2380 if (R__b.IsReading()) {
2381
2382 UInt_t R__s;
2383 UInt_t R__c;
2384 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2385
2386 if (R__v > 2) {
2387 R__b.ReadClassBuffer(RooDataHist::Class(),this,R__v,R__s,R__c);
2388 R__b.CheckByteCount(R__s, R__c, RooDataHist::IsA());
2389 initialize(nullptr, false);
2390 } else {
2391
2392 // Legacy dataset conversion happens here. Legacy RooDataHist inherits from RooTreeData
2393 // which in turn inherits from RooAbsData. Manually stream RooTreeData contents on
2394 // file here and convert it into a RooTreeDataStore which is installed in the
2395 // new-style RooAbsData base class
2396
2397 // --- This is the contents of the streamer code of RooTreeData version 2 ---
2398 UInt_t R__s1;
2399 UInt_t R__c1;
2400 Version_t R__v1 = R__b.ReadVersion(&R__s1, &R__c1); if (R__v1) { }
2401
2403 TTree* X_tree(nullptr) ; R__b >> X_tree;
2404 RooArgSet X_truth ; X_truth.Streamer(R__b);
2406 R__b.CheckByteCount(R__s1, R__c1, TClass::GetClass("RooTreeData"));
2407 // --- End of RooTreeData-v1 streamer
2408
2409 // Construct RooTreeDataStore from X_tree and complete initialization of new-style RooAbsData
2410 _dstore = std::make_unique<RooTreeDataStore>(X_tree,_vars);
2411 _dstore->SetName(GetName()) ;
2412 _dstore->SetTitle(GetTitle()) ;
2413 _dstore->checkInit() ;
2414
2416 R__b >> _arrSize;
2417 delete [] _wgt;
2418 _wgt = new double[_arrSize];
2419 R__b.ReadFastArray(_wgt,_arrSize);
2420 delete [] _errLo;
2421 _errLo = new double[_arrSize];
2422 R__b.ReadFastArray(_errLo,_arrSize);
2423 delete [] _errHi;
2424 _errHi = new double[_arrSize];
2425 R__b.ReadFastArray(_errHi,_arrSize);
2426 delete [] _sumw2;
2427 _sumw2 = new double[_arrSize];
2428 R__b.ReadFastArray(_sumw2,_arrSize);
2429 delete [] _binv;
2430 _binv = new double[_arrSize];
2432 tmpSet.Streamer(R__b);
2433 double tmp;
2434 R__b >> tmp; //_curWeight;
2435 R__b >> tmp; //_curWgtErrLo;
2436 R__b >> tmp; //_curWgtErrHi;
2437 R__b >> tmp; //_curSumW2;
2438 R__b >> tmp; //_curVolume;
2439 R__b >> _curIndex;
2440 R__b.CheckByteCount(R__s, R__c, RooDataHist::IsA());
2441 }
2442
2443 } else {
2444
2445 R__b.WriteClassBuffer(RooDataHist::Class(),this);
2446 }
2447}
2448
2449
2450////////////////////////////////////////////////////////////////////////////////
2451/// Return event weights of all events in range [first, first+len).
2452/// If cacheValidEntries() has been called, out-of-range events will have a weight of 0.
2453std::span<const double> RooDataHist::getWeightBatch(std::size_t first, std::size_t len, bool sumW2 /*=false*/) const {
2454 return {(sumW2 && _sumw2 ? _sumw2 : _wgt) + first, len};
2455}
2456
2457
2458////////////////////////////////////////////////////////////////////////////////
2459/// Hand over pointers to our weight arrays to the data store implementation.
2461 _dstore->setExternalWeightArray(_wgt, _errLo, _errHi, _sumw2);
2462}
2463
2464
2465////////////////////////////////////////////////////////////////////////////////
2466/// Return reference to VarInfo struct with cached histogram variable
2467/// information that is frequently used for histogram weights retrieval.
2468///
2469/// If the `_varInfo` struct was not initialized yet, it will be initialized in
2470/// this function.
2472
2473 if(_varInfo.initialized) return _varInfo;
2474
2475 auto& info = _varInfo;
2476
2477 {
2478 // count the number of real vars and get their indices
2479 info.nRealVars = 0;
2480 size_t iVar = 0;
2481 for (const auto real : _vars) {
2482 if (dynamic_cast<RooRealVar*>(real)) {
2483 if(info.nRealVars == 0) info.realVarIdx1 = iVar;
2484 if(info.nRealVars == 1) info.realVarIdx2 = iVar;
2485 ++info.nRealVars;
2486 }
2487 ++iVar;
2488 }
2489 }
2490
2491 {
2492 // assert that the variables are either real values or categories
2493 for (unsigned int i=0; i < _vars.size(); ++i) {
2494 if (_lvbins[i].get()) {
2495 assert(dynamic_cast<const RooAbsReal*>(_vars[i]));
2496 } else {
2497 assert(dynamic_cast<const RooAbsCategoryLValue*>(_vars[i]));
2498 }
2499 }
2500 }
2501
2502 info.initialized = true;
2503
2504 return info;
2505}
#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:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
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:148
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:777
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 ...
static constexpr int DefaultNBins
Historical default number of bins, injected by routines that need a concrete bin count when a variabl...
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...
Implementation of RooAbsBinning that provides a uniform binning in 'n' bins between the range end poi...
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:2994
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:9293
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:5239
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:227
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