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