root icon indicating copy to clipboard operation
root copied to clipboard

[RF] Values of RooProdPdfs in a RooAbsPdf should not depend on its factors `normRange()`

Open guitargeek opened this issue 3 years ago • 3 comments

Describe the bug

If a RooProdPdf is in a RooAddPdf, its values change if one changes the normalization range of its factors with RooAbsPdf::normRange().

Expected behavior

The values of a RooProdPdf should not depend on the normRange() of its factors, because the RooProdPdf is responsible for normalizing itself.

To Reproduce

Enable the new unit test in testRooProdPdf shipped with https://github.com/root-project/root/pull/11485.

Setup

ROOT master on Arch Linux.

Additional context

It is important now to fix the issues related to the RooAbsPdf::normRange() feature, because as of https://github.com/root-project/root/pull/11455 it is used in multi-range fits. Thus, we need to make sure it's less fragile.

After this issue is fixed, it should be verified with stressRooFit that things would still work if one were to set the normalization ranges of all PDFs in the computation graph in RooAbsOptTestStatistic::initSlave() not just the top-level PDF:

For debugging, it could be helpful to replace the RooProdPdfs with RooFixedProdPdf objects, which explicitly represent the conputation graph of a RooProdPdf for a given normalization set without internal caching:

         if(auto prodPdf = dynamic_cast<RooProdPdf *>(pdf)) {
         auto normalizedPdf = std::make_unique<RooFixedProdPdf>(*prodPdf, currNormSet);

         replaceArg(*normalizedPdf, *pdf);

         newNodes.emplace_back(std::move(normalizedPdf));

         continue;
         }

guitargeek avatar Oct 04 '22 01:10 guitargeek

Related forum post: https://root-forum.cern.ch/t/slow-performance-in-limited-range-fit-with-roofit/52834/2

guitargeek avatar Dec 20 '22 13:12 guitargeek

Another related forum post: https://root-forum.cern.ch/t/plot-normalization-after-rooaddpdf-fixaddcoefrange/54480

guitargeek avatar Jun 05 '23 23:06 guitargeek

The underlying problem is that multi-range integrals in the RooProdPdf don't work:

  // Define observables x,y
  RooRealVar x("x","x",-10,10) ;
  RooRealVar y("y","y",-10,10) ;

  // Construct the background pdf (flat in x,y)
  RooUniform px("px","px",x) ;
  RooUniform py("py","py",y) ;
  RooProdPdf bkg("bkg","bkg",px,py) ;

  // Construct the SideBand1,SideBand2,Signal regions
  //
  //                    |
  //      +-------------+-----------+
  //      |             |           |
  //      |    Side     |   Sig     |
  //      |    Band1    |   nal     |
  //      |             |           |
  //    --+-------------+-----------+--
  //      |                         |
  //      |           Side          |
  //      |           Band2         |
  //      |                         |
  //      +-------------+-----------+
  //                    |

  x.setRange("SB1",-10,+10) ;
  y.setRange("SB1",-10,0) ;

  x.setRange("SB2",-10,0) ;
  y.setRange("SB2",0,+10) ;

  x.setRange("SIG",0,+10) ;
  y.setRange("SIG",0,+10) ;

  x.setRange("FULL",-10,+10) ;
  y.setRange("FULL",-10,+10) ;

  RooArgSet deps{x, y};

  bkg.setNormRange("SB1,SB2");

  RooArgSet normSet{x, y};

  // Doesn't work
  std::cout << bkg.getVal(normSet) << std::endl;

guitargeek avatar Jun 05 '23 23:06 guitargeek