Details
-
Bug
-
Resolution: Fixed
-
High
-
6.14/00
-
None
-
Ubuntu 18.04, 4.15
Description
I've encountered a problem with fits using two or more named ranges. The fits converge fine, but give different results when using multiple named ranges (with the named range values being the same as the default ones).
As a crosscheck, I keep the named ranges same as the default ones. Real use case would of course be different.
If anyone could shed some light on this I'd be very grateful.
Note: A similar problem was recently posted here. However, in the case of more dimensions, such as the one I present here, the problem is much more serious.
Note 2: A similar problem was also reported in ROOT-7937, however the solution proposed there (setNormRange()), doesn't seem to work.
Minimal Working Example
Here is a minimal working example (very slightly adapted rf304_uncorrprod.C).
#ifndef __CINT__
|
#include "RooGlobalFunc.h" |
#endif
|
#include "RooRealVar.h" |
#include "RooDataSet.h" |
#include "RooGaussian.h" |
#include "RooProdPdf.h" |
#include "TCanvas.h" |
#include "TAxis.h" |
#include "RooPlot.h" |
using namespace RooFit ;
|
|
|
|
void mod_rf304_uncorrprod() |
{
|
// C r e a t e c o m p o n e n t p d f s i n x a n d y |
// ---------------------------------------------------------------- |
|
|
// Create two p.d.f.s gaussx(x,meanx,sigmax) gaussy(y,meany,sigmay) and its variables |
RooRealVar x("x", "x", -5, 5); |
RooRealVar y("y", "y", -5, 5); |
|
|
RooRealVar meanx("mean1", "mean of gaussian x", 2.0, 0.0, 3.0); |
RooRealVar meany("mean2", "mean of gaussian y", -2.0, -3.0, 0.0); |
RooRealVar sigmax("sigmax", "width of gaussian x", 1.0, 0.0, 2.0); |
RooRealVar sigmay("sigmay", "width of gaussian y", 5.0, 0.0, 10.0); |
|
|
RooGaussian gaussx("gaussx", "gaussian PDF", x, meanx, sigmax); |
RooGaussian gaussy("gaussy", "gaussian PDF", y, meany, sigmay); |
|
|
// C o n s t r u c t u n c o r r e l a t e d p r o d u c t p d f |
// ------------------------------------------------------------------- |
|
|
// Multiply gaussx and gaussy into a two-dimensional p.d.f. gaussxy |
RooProdPdf gaussxy("gaussxy", "gaussx * gaussy", RooArgList(gaussx, gaussy)); |
|
|
// S a m p l e p d f , p l o t p r o j e c t i o n o n x a n d y |
// --------------------------------------------------------------------------- |
|
|
// Generate 10000 events in x and y from gaussxy |
RooDataSet *data = gaussxy.generate(RooArgSet(x, y), 10000) ; |
|
|
x.setRange("a", -5, 5); |
y.setRange("b", -5, 5); |
RooFitResult* result = gaussxy.fitTo(*data, Save(true), Range("")); |
result->Print();
|
}
|
Results
The MWE works just fine and gives the following result:
RooFitResult: minimized FCN value: 36828.5, estimated distance to minimum: 7.98083e-07 |
covariance matrix quality: Full, accurate covariance matrix
|
Status : MIGRAD=0 HESSE=0 |
|
|
Floating Parameter FinalValue +/- Error
|
-------------------- --------------------------
|
mean1 2.0084e+00 +/- 1.01e-02 |
mean2 -2.1360e+00 +/- 1.64e-01 |
sigmax 1.0019e+00 +/- 7.34e-03 |
sigmay 5.0329e+00 +/- 1.83e-01 |
I get the exact same result when changing the Range("") to Range("a") or Range("b"). However, when trying to use both ranges - Range("a,b"), I get very different errors (in some cases even the central values change):
RooFitResult: minimized FCN value: 73657.1, estimated distance to minimum: 1.62972e-06 |
covariance matrix quality: Full, accurate covariance matrix
|
Status : MIGRAD=0 HESSE=0 |
|
|
Floating Parameter FinalValue +/- Error
|
-------------------- --------------------------
|
mean1 2.0084e+00 +/- 7.14e-03 |
mean2 -2.1360e+00 +/- 1.16e-01 |
sigmax 1.0019e+00 +/- 5.19e-03 |
sigmay 5.0329e+00 +/- 1.29e-01 |
Additional Observations
It's worth noting, that when I change the ranges in this way
x.setRange("a", -5, 0); |
x.setRange("b", 0, 5); |
and use Range("a,b") the result is also different from the nominal one, although not by that much this time:
Floating Parameter FinalValue +/- Error
|
-------------------- --------------------------
|
mean1 2.0114e+00 +/- 1.10e-02 |
mean2 -2.1346e+00 +/- 1.64e-01 |
sigmax 9.9857e-01 +/- 8.79e-03 |
sigmay 5.0316e+00 +/- 1.82e-01 |
setNormRange() Approach
Lorenzo Moneta explained in ROOT-7937, that the way to go in this case is to use setNormRange(). However, that seems to give much worse result than the previous approaches. Changing the above code to
x.setRange("a", -5, 5); |
x.setRange("b", -5, 5); |
gaussxy.setNormRange("a,b"); |
RooFitResult* result = gaussxy.fitTo(*data, Save(true)); |
yields a very wrong result:
RooFitResult: minimized FCN value: 69808.9, estimated distance to minimum: 4.28253e-05 |
covariance matrix quality: Full, accurate covariance matrix
|
Status : MIGRAD=0 HESSE=0 |
|
|
Floating Parameter FinalValue +/- Error
|
-------------------- --------------------------
|
mean1 2.0038e+00 +/- 7.04e-03 |
mean2 -3.0000e+00 +/- 2.17e-03 |
sigmax 7.0357e-01 +/- 3.52e-03 |
sigmay 3.1021e+00 +/- 2.09e-02 |
Adding Range("a,b") to the fitTo() yields
RooFitResult: minimized FCN value: 139618, estimated distance to minimum: 8.56935e-05 |
covariance matrix quality: Full, accurate covariance matrix
|
Status : MIGRAD=0 HESSE=0 |
|
|
Floating Parameter FinalValue +/- Error
|
-------------------- --------------------------
|
mean1 2.0038e+00 +/- 4.98e-03 |
mean2 -3.0000e+00 +/- 1.08e-03 |
sigmax 7.0357e-01 +/- 2.49e-03 |
sigmay 3.1021e+00 +/- 1.48e-02 |
Workaround
In an unbinned fit, one could probably just reduce() the dataset to get the desired outcome. Not very elegant though.