How to convert C function with array of parameters to RooGenericPdf?

Dear experts,

I would like to continue with the discussions in

Instead of the function in the post, if I have a C function with a structure

Double_t function(Double_t *x, Double_t *p) {
// containing x[0], p[0], p[1], p[2], p[3]
}

How can I create RooGenericPdf from this?

auto functionFormula = "function(...)";
RooGenericPdf pdf("pdf", "pdf", functionFormula, {...});

I can’t think of any way to implement the method in the post.
It is easy to convert this C function into TF1, but it seems difficult to convert the TF1 into pdf.

Thank you in advance.

Best,
Marco

Hi @Marco1224,
thanks for reaching out!
Can you provide more details? Do you what to convert to PDF a C function that takes into account an arbitrary number of input values?
Cheers,
Monica

Dear @mdessole,

Thank you for your reply.
Yes, I would like to convert a C function with many parameters (as reflected in Double_t *p) to a PDF.
And the number of parameters may change.

The context is that I would like to make a PDF with a very long function with many parameters.
If I directly input char formula expression into RooGenericPdf, it would be very lengthy.
Instead, I would like to try to define a C double function first.
That’s why I was referencing the method in the post I mentioned, but the way to define the arguments in the C function is different, and I could not figure out the formula expression accepted by RooGenericPdf().

Best regards,
Marco

I add in the loop our roofit expert @jonas

Hi @Marco1224!

There is no interface in RooFit to directly do this, but you can use ROOT::Math to help you out. There is this ROOT::Math::Functor class that wraps functions with array inputs, and then RooFit has a class to wrap such functors.

Example:

double myfunction(double const *x, double const *p) {
   return x[0] * p[0] * p[1] * p[2] * p[3];
}

RooRealVar x0{"x0", "x0", 1., 0., 10.};
RooRealVar p0{"p0", "p0", 1., 0., 10.};
RooRealVar p1{"p1", "p1", 2., 0., 10.};
RooRealVar p2{"p2", "p2", 3., 0., 10.};
RooRealVar p3{"p3", "p3", 4., 0., 10.};

RooArgList argList{x0, p0, p1, p2, p3};

// The Functor wraps a fuction that only takes one array,
// so you have to pack both arrays into one.
ROOT::Math::Functor functor{
    [](double const *x){ return myfunction(x, x + 1); },
    1 + 4 // the length of the concatenated array
};
// Wrapping a ROOT::Math::Functor in RooFit is easy
RooFunctorBinding rooFunc{"roo_func", "roo_func", functor, argList};

Just make sure the ROOT::Math::Functor doesn’t get destroyed before the RooFunctorBinding, because the binding only owns a pointer to the functor, which you have to manage yourself.

I hope this helps you with your work!

Cheers,
Jonas

Dear @jonas ,

Thank you very much for your suggestions.

I have tried to implement your method.
I could get the pdf by plugging the functor into RooFunctorPdfBinding.
However, after applying RooExtendPdf and RooAddPdf, the normalization after fitting is incorrect.
I think it has something to do with other parts of the code because I checked the functor method is working with a simple Gaussian.
At the end, I come up with a workaround by creating a const char* function instead of a double function.

Best regards,
Marco

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