Multi-Range Simultaneous Fit: SplitRange() functionality not working

PS (alternative):
At the bottom of tutorials/roofit/rf404_categories.C in your root folder, there’s also something on setting ranges for each category.
https://root.cern.ch/doc/master/rf404__categories_8C_source.html

Hi Stephan,

I have done as you suggested. I label the ranges according the the number assigned to them:

// DEFINE INDEX CATEGORIES
  RooCategory neutral("neutral", "neutral");
  neutral.defineType("pi0");
  neutral.defineType("gamma");

  neutral.Print("V");

  deltaMass.setRange("range_0", 135, 210);
  deltaMass.setRange("range_1", 50, 210);

The following is my FitTo() command:

  std::unique_ptr<RooFitResult> result = std::unique_ptr<RooFitResult>(
      simPdf.fitTo(combData, RooFit::Extended(true),
                   RooFit::Range("range"),
                   RooFit::SplitRange(true),
                   RooFit::Save(),
                   RooFit::Strategy(2), RooFit::Minimizer("Minuit2"),
                   RooFit::Offset(true)));

I can see that the range names are labelled with the correct index because I get this output:

— RooAbsCategory —
Value is “pi0” (0)
Has the following possible values:
pi0 = 0
gamma = 1
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘range_0’ created with bounds [135,210]
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘range_1’ created with bounds [50,210]

But unfortunately the simultaneous fit is still over 0-210 MeV, for both categories!

Thanks,
Alex

Hi Stephan,

Looking at the documentation, the member function setRange in RooCategory only accepts arguments in the form of a named list:
https://root.cern.ch/doc/v610/classRooCategory.html#a33a5d3909f8aaf9e5549a2aeaf96e3f0

I interpret from this, and the example you sent, that this function creates a range defined by a certain category rather than allowing the user to alter a variable range within a given category. Does that make sense to you?

Thanks,
Alexandra

Yes and no. It’s not a list in a programming sense. It, however, doesn’t seem to apply to your problem. Apparently, this is to define a “range” that automatically switches on/off certain categories.

So we are back to SplitRange. Was there any output as to what range the fit was using?

Also, there is the following output related to RooAbsTestStatistic:

RooAbsTestStatistic::initSimMode: creating slave calculator #0 for state pi0 (11000 dataset entries)
reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named range
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘NormalizationRangeForrange’ created with bounds [0,210]
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘fit_pi0’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) fixing interpretation of coefficients of any RooAddPdf to full domain of observables
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
RooAbsTestStatistic::initSimMode: creating slave calculator #1 for state gamma (11000 dataset entries)
reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named range
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘fit_gamma’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) fixing interpretation of coefficients of any RooAddPdf to full domain of observables

So it is creating different ranges but they are called ‘fit_pi0’ and ‘fit_gamma’ and go from 0-210 MeV… It doesn’t seem to find the ranges I specify?

… I therefore edited my range names to:

  deltaMass.setRange("fit_pi0", 135, 210);
  deltaMass.setRange("fit_gamma", 50, 210);

and called RooFit::Range(“fit”), but the same thing happened, only the output then said:

[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named fit_pi0
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘NormalizationRangeForfit_pi0’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) fixing interpretation of coefficients of any RooAddPdf to full domain of observables
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M|NormalizationRangeForfit_pi0]_Norm[Delta_M]) using numeric integrator RooIntegrator1D to calculate
Int(Delta_M) RooAbsTestStatistic::initSimMode: creating slave calculator #1 for state gamma (11000 dataset entries) reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named fit_gamma
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘NormalizationRangeForfit_gamma’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) fixing interpretation of coefficients of any RooAddPdf to full domain of observables
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M|NormalizationRangeForfit_gamma]_Norm[Delta_M]) using numeric integrator RooIntegrator1D to calcu
late Int(Delta_M)

Out of interest I then changed fit to NormalizationRangeForfit and then the output changed the names to NormalizationRangeForfitNormalizationRangeForfit_gamma/pi0.

I really don’t understand what’s happening here…

Hi Stephan,

Yes, see the posts following on from my last reply (sorry, I think I replied to my own message therefore perhaps you were not notified):

Thanks,
Alex

It’s normal that a range fit_<someName> is created if no range is given. Since you now created this by hand, did you verify that it was/wasn’t using this range in the fit?

I tried the debug setting to get a more verbose output, and I searched for any messages to do with Range, but there was no mention of the ‘range_0’ and ‘range_1’ that I specify, except at the beginning when they are created. Instead ranges named NormalizationRangeForrange and fit_<someName>, created by RooFit, are used in the fit.

Yes, that’s why I was asking. Since you created a range fit_pi0, which is the same that RooFit would have created automatically, did it use this range in the fit?

That still doesn’t solve the problem of getting this to work properly, but I’m still trying to investigate in which circumstances certain ranges are picked up.

Hi Stephan,

No, if you see my second reply - it then replaced the range names created internally used in the fit to NormalizationRangeForfit_pi0 and NormalizationRangeForfit_gamma.
I tried using these range names, and then the ones used were called NormalizationRangeForfitNormalizationRangeForfit_pi0 and NormalizationRangeForfitNormalizationRangeForfit_gamma.

I have attached a stand alone macro that you can play around with if that is easier,SimToy.cpp (9.0 KB)

That will be much easier. However, I cannot dedicate any time before mid next week.

Hi Stephan,

The example I attached is the same code as the one I explained originally, but I added an additional gaussian at 25 MeV in the gamma category so that it would be easier to see whether the PDF was being fit to the data below 50 MeV.
If you could get back to me mid-next week, when you become available, I would really appreciate it.

Thanks,
Alexandra

Hi Stefan,

Have you managed to take a look at this yet?

Best wishes,
Alexandra

Hi Alexandra,

could you please try

  deltaMass.setRange("range_{pi0}", 135, 210);
  deltaMass.setRange("range_{gamma}", 50, 210);

Maybe we simply forgot the curly braces.

Hi Stephan,

Same output - the fit still automatically creates a new range for the Delta_M variable, over the whole range:

(I also tried range_{0} and range_{1} but got the same result)

[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘range_{pi0}’ created with bounds [135,210]
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘range_{gamma}’ created with bounds [50,210]
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
reduceEng varSubset = (Delta_M) _wgtVar =
RooAbsTestStatistic::initSimMode: creating slave calculator #0 for state pi0 (11000 dataset entries)
reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named range_pi0
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘NormalizationRangeForrange_pi0’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(pi0) fixing interpretation of coefficients of any RooAddPdf to full domain of observables
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
RooAbsTestStatistic::initSimMode: creating slave calculator #1 for state gamma (11000 dataset entries)
reduceEng varSubset = (Delta_M) _wgtVar =
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named range_gamma
[#1] INFO:Eval – RooRealVar::setRange(Delta_M) new range named ‘NormalizationRangeForrange_gamma’ created with bounds [0,210]
[#1] INFO:Fitting – RooAbsOptTestStatistic::ctor(gamma) fixing interpretation of coefficients of any RooAddPdf to full domain of observables
[#1] INFO:NumericIntegration – RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
[#1] INFO:Fitting – RooAbsTestStatistic::initSimMode: created 2 slave calculators.

Hi Alexandra,

I ran your example, and the switch seems to work. The diff of the two examples (SplitRange commented out) reads:

--- arolling_out_noSplit.txt	2019-03-26 14:19:59.180227256 +0100
+++ arolling_out.txt	2019-03-26 14:19:20.751357488 +0100
@@ -12,13 +12,11 @@
 [#1] INFO:NumericIntegration -- RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
 [#1] INFO:NumericIntegration -- RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
 RooAbsTestStatistic::initSimMode: creating slave calculator #0 for state pi0 (11000 dataset entries)
-[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named range
-[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'fit_pi0' created with bounds [0,210]
+[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named range_pi0
 [#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(pi0) fixing interpretation of coefficients of any RooAddPdf component to range range
 [#1] INFO:NumericIntegration -- RooRealIntegral::init(pdfDeltaBkgPi0_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
 RooAbsTestStatistic::initSimMode: creating slave calculator #1 for state gamma (11000 dataset entries)
-[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named range
-[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'fit_gamma' created with bounds [0,210]
+[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named range_gamma
 [#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(gamma) fixing interpretation of coefficients of any RooAddPdf component to range range
 [#1] INFO:NumericIntegration -- RooRealIntegral::init(pdfDeltaBkgGamma_Int[Delta_M]) using numeric integrator RooIntegrator1D to calculate Int(Delta_M)
 [#1] INFO:Fitting -- RooAbsTestStatistic::initSimMode: created 2 slave calculators.
@@ -32,51 +30,45 @@
 [#1] INFO:Minization --  The following expressions have been identified as constant and will be precalculated and cached: (pdfDeltaBkgGamma)
 [#1] INFO:Minization --  The following expressions will be evaluated in cache-and-track mode: (pdfDeltaSigGamma1,pdfDeltaSigGamma2)
 Minuit2Minimizer: Minimize with max-calls 5500 convergence for edm < 1 strategy 2
-[#1] INFO:Minization -- RooNLLVar::evaluatePartition(pi0) first = 0 last = 11000 Likelihood offset now set to -36519.5
-[#1] INFO:Minization -- RooNLLVar::evaluatePartition(gamma) first = 0 last = 11000 Likelihood offset now set to -25446.4
-MnSeedGenerator: for initial parameters FCN = 3.637978807092e-12
-MnSeedGenerator: Initial state:   - FCN = 3.637978807092e-12 Edm =       7937.4 NCalls =     45
-MnSeedGenerator: run Hesse - new state:   - FCN = 3.637978807092e-12 Edm =      7324.92 NCalls =    145
+[#1] INFO:Minization -- RooNLLVar::evaluatePartition(pi0) first = 0 last = 10992 Likelihood offset now set to -36514.9
+[#1] INFO:Minization -- RooNLLVar::evaluatePartition(gamma) first = 0 last = 11000 Likelihood offset now set to -25446.5
+MnSeedGenerator: for initial parameters FCN = -1.091393642128e-11
+MnSeedGenerator: Initial state:   - FCN = -1.091393642128e-11 Edm =      7937.74 NCalls =     45
+MnSeedGenerator: run Hesse - new state:   - FCN = -1.091393642128e-11 Edm =      7255.47 NCalls =    145
 VariableMetric: start iterating until Edm is < 0.001

and then it converges to a different minimum. It seems to work with a range named just "range_pi0". I tested by setting the range to crazy values such as

  deltaMass.setRange("range_gamma", 200, 210);

and that also works (it breaks the fit, as it should).

What was giving you the impression that the fit it is being carried out on the full range?

Hi Stephan,

What makes me believe it is not working is that the ranges fit_gamma and fit_pi0 that you have pointed out above explicitly say in the result that they are covering [0,210] and not what we specify in the macro?

These are some relevant lines from my output:

[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'range_pi0' created with bounds [135,210]
[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'range_gamma' created with bounds [200,210]
...
[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(pi0) constructing test statistic for sub-range named range
[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'fit_pi0' created with bounds [0,210]
...
[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(gamma) constructing test statistic for sub-range named range
[#1] INFO:Eval -- RooRealVar::setRange(Delta_M) new range named 'fit_gamma' created with bounds [0,210]

Also, I found that editing ‘range_gamma’ from 50 - 210, to 200 - 210 gave the same minimum in both cases? I found the the fit only breaks if I include SplitRange, but this breaks it in both cases, not just the latter.

As well as this, the output of the macro is a file with the PFDs plotted onto the toy datasets - you can see that the PDF is plotted over the full range, on top of the data, and not only in the ranges specified. This is from the output:

[#1] INFO:Plotting -- RooAbsPdf::plotOn(pdfGamma) p.d.f was fitted in range and no explicit plot,norm range was specified, using fit range as default
[#1] INFO:Plotting -- RooAbsPdf::plotOn(pdfGamma) only plotting range 'fit_gamma'
[#1] INFO:Plotting -- RooAbsPdf::plotOn(pdfGamma) p.d.f. curve is normalized using explicit choice of ranges 'fit_gamma'

So I still believe that it is not finding the values for the range that I specify.

Sorry for the delay in replying, I was away.

Thanks,
Alexandra

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.