Skip to content

Commit

Permalink
[RF] New unit test for SplitRange() feature in RooAbsPdf::fitTo()
Browse files Browse the repository at this point in the history
The recent commit 922dec5 fixed GitHub issue root-project#11396, but there was
still no unit test implemented with the reproducer code from that issue.
This commit is implementing such a unit test.
  • Loading branch information
guitargeek committed Sep 25, 2022
1 parent 1a8abc2 commit 4e61a64
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions roofit/roofitcore/test/testRooSimultaneous.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,71 @@ TEST(RooSimultaneous, CategoriesWithNoPdf)
m1.setError(0.0);
sim.fitTo(*ds, BatchMode(true), PrintLevel(-1));
}

/// GitHub issue #11396.
/// Test whether the RooFit::SplitRange() command argument for simultaneous
/// fits is correctly considered in multi-range fits.
TEST(RooSimultaneous, MultiRangeFitWithSplitRange)
{
using namespace RooFit;

int nEventsInCat = 11000;

RooWorkspace wsCat1{"wsCat1"};
wsCat1.factory("Gaussian::pdf_cat1(x_cat1[0,10],muCat1[4,0,10],sigma_cat1[1.0,0.1,10.0])");
RooAbsPdf &pdfCat1 = *wsCat1.pdf("pdf_cat1");
RooRealVar &xCat1 = *wsCat1.var("x_cat1");
xCat1.setRange("SideBandLo_cat1", 0, 2);
xCat1.setRange("SideBandHi_cat1", 6, 10);
std::unique_ptr<RooDataSet> dsCat1{pdfCat1.generate(xCat1, nEventsInCat)};

RooWorkspace wsCat2{"wsCat2"};
wsCat2.factory("Gaussian::pdf_cat2(x_cat2[0,10],muCat2[6,0,10],sigma_cat2[1.0,0.1,10.0])");
RooAbsPdf &pdfCat2 = *wsCat2.pdf("pdf_cat2");
RooRealVar &xCat2 = *wsCat2.var("x_cat2");
xCat2.setRange("SideBandLo_cat2", 0, 4);
xCat2.setRange("SideBandHi_cat2", 8, 10);
std::unique_ptr<RooDataSet> dsCat2{pdfCat1.generate(xCat2, nEventsInCat)};

RooCategory indexCat{"cat", "cat"};
indexCat.defineType("cat1");
indexCat.defineType("cat2");

RooSimultaneous simPdf{"simPdf", "", indexCat};
simPdf.addPdf(pdfCat1, "cat1");
simPdf.addPdf(pdfCat2, "cat2");

std::map<std::string, RooDataSet *> dsmap{{"cat1", dsCat1.get()}, {"cat2", dsCat2.get()}};

RooDataSet combData{"combData", "", {xCat1, xCat2}, Index(indexCat), Import(dsmap)};

std::unique_ptr<RooAbsReal> nll1{pdfCat1.createNLL(*dsCat1, Range("SideBandLo_cat1,SideBandHi_cat1"))};
std::unique_ptr<RooAbsReal> nll2{pdfCat2.createNLL(*dsCat2, Range("SideBandLo_cat2,SideBandHi_cat2"))};
std::unique_ptr<RooAbsReal> nllSim{simPdf.createNLL(combData, Range("SideBandLo,SideBandHi"), SplitRange())};

const double nll1Val = nll1->getVal();
const double nll2Val = nll2->getVal();
// In simultaneous PDFs, the probability is normalized over the categories,
// so we have to do that as well when computing the reference value. Since
// we do a ranged fit, we have to consider the ranges when calculating the
// number of events in data.
double nCat1InRange = std::unique_ptr<RooAbsData>
{
dsCat1->reduce(CutRange("SideBandLo_cat1,SideBandHi_cat1"))
} -> sumEntries();
double nCat2InRange = std::unique_ptr<RooAbsData>
{
dsCat2->reduce(CutRange("SideBandLo_cat2,SideBandHi_cat2"))
} -> sumEntries();
const double nllSimRefVal = (nCat1InRange + nCat2InRange) * std::log(2) + nll1Val + nll2Val;

const double nllSimVal = nllSim->getVal();

// For now, we can't cross check the likelihood value and the unit test
// only checks whether the simultaneous likelihood can be crated with the
// SplitRange() argument without the range overlap checks failing. Once the
// issue with multi-range simultaneous likelihood values is fixed, this can
// be commented out:
//
// EXPECT_FLOAT_EQ(nllSimVal, nllSimRefVal);
}

0 comments on commit 4e61a64

Please sign in to comment.