Potential bug in RooWrapperPdf/RooDataSet for unbinned data

Hi,
I tried to fit some data by using the unbinned data fitting option RooFit provides. But there has been a really bizarre issue. Seeing the plots below, it seems that the first and last point that are still in the fit range get updated with a new value.


(Those are the same datasets but with different fit ranges)
These offsets then interfere with the fit (which to me in this case seems obvious). The error message being:

I also plotted the dataset with a range from -infinity to infinity (without the fit) where the plot and dataset seems totally fine.

Here my code:

std::vector<double> RooFit_Vector(TH1* histo, std::vector<double> events, const FunctionType FT, const double min, const double max)
{
    RooRealVar Observable("events", "events in vector", min, max);
    RooDataSet data("data", "data", Observable);                                    

    // for (double event:events){
    //     Observable.setVal(event);
    //     data.add(RooArgSet(Observable));
    // }

    for (int i=0; i < static_cast<int>(events.size());i++)
    {
        Observable.setVal(events[i]);
        data.add(RooArgSet(Observable));
    }

    // RooRealVar ampl ("ampl"     , "amplitude"   , 10'000.0           , 1.0                      , 1'000'000.0 ); 
    RooRealVar mean ("mean"     , "mean of fit" , (min+max)/2 + 0.1  , min                      , max         );
    RooRealVar sigma("sigma"    , "sigma of fit", 250                , 0.01                     , 500         );
    RooRealVar tail1("tail1"    , "tail1"       , 100'000.0          , 0.01                     , 1'000'000.0 );
    RooRealVar tail2("tail2"    , "tail2"       , 100'000.0          , 0.01                     , 1'000'000.0 );


    RooPlot* ObservableFrame = Observable.frame(Range(histo->GetXaxis()->GetXmin(), histo->GetXaxis()->GetXmax()), Bins(histo->GetNbinsX())); 
    ObservableFrame->SetTitle(histo->GetName());

    TF1        *mg      = new TF1("my_gauss", *my_gauss_2, min + 1, max - 1, 2, 1);
    RooAbsReal *pre_pdf = bindFunction(mg, Observable, RooArgList(mean, sigma));
    
    if (FT == FunctionType::kGaussTailLeft){
        *mg     = TF1("my_gaussTL", *gauss_tail_left_2,  min + 1, max - 1, 3, 1);
        pre_pdf = bindFunction(mg, Observable, RooArgList(mean, sigma, tail1));
    }
    else if (FT == FunctionType::kGaussTailRight){
        *mg     = TF1("my_gaussTR", *gauss_tail_right_2, min + 1, max - 1, 3, 1);
        pre_pdf = bindFunction(mg, Observable, RooArgList(mean, sigma, tail1));
    }
    else if (FT == FunctionType::kGaussTailBoth){
        *mg     = TF1("my_gaussTB", *gauss_tail_both_2,  min + 1, max - 1, 4, 1);
        pre_pdf = bindFunction(mg, Observable, RooArgList(mean, sigma, tail1, tail2));
    }

    RooWrapperPdf *pdf = new RooWrapperPdf("pdf", "pdf", *pre_pdf); 

    //RooWrapperPdf *pdf = CreateCustomPdf(FT, par, min, max, Observable);
    RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);

    data.plotOn(ObservableFrame, MarkerSize(0.1), XErrorSize(0.1), DataError(0.1) );

    pdf->fitTo(data, PrintLevel(-1), Minimizer("Minuit2","minimize"), RecoverFromUndefinedRegions(30));
    pdf->plotOn(ObservableFrame);  

This also just happens to the first set of data that I load into this function. All the other datasets and their fits are totally normal (and are working really well actually)

If it is my own incompetence that is producing the error then please correct me.
Otherwise I think that this might just be a bug.

Best Regards
Ludwig

Dear @Ludwig ,

Thank you for your report. I will invite @jonas to take a look.

Cheers,
Vincenzo

The problem is that the observable values are clipped to the range of the corresponding RooRealVar when filling a dataset. You can add a check if events[i] is actually in your fit rage:

    RooArgSet observables{observable};
    for (int i=0; i < static_cast<int>(events.size());i++)
    {
        if(observable.inRange(events[i], nullptr)) {
            observable.setVal(events[i]);
            data.add(observables);
        }
    }

Two more suggestions:

  • Better call the variable observable (lower-case), to follow the standard variable name convention
  • Create the RooArgSet outside the event loop to avoid overhead

I hope this helps!

Cheers,
Jonas

Hi Jonas,

First of all thank you for the reply.

The floating points are indeed gone but sadly the fit is still flawed.

Do you have any other ideas on why this is happening?
The error message remains the same as before.

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