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