How to convolute a RooGenericPdf with a gaussian function?

Hi! I want to convolute a RooGenericPdf with a gaussian function. But it always failed by using RooFFTConvPdf function. Here is my code. Thanks for your help!

void test(){
RooRealVar *obs_var = new RooRealVar(“obs_var”, “obs_var”,120,110,180) ;

RooRealVar *tau = new RooRealVar(“tau”,“tau”,-0.02,-10,-0.) ;
RooExponential *exp = new RooExponential(“model”,“model”,*obs_var,*tau) ;
RooRealVar *mean = new RooRealVar(“mean”,“mean”,10,0,180) ;
RooRealVar *sigma = new RooRealVar(“sigma”,“sigma”,20,-10, 20) ;
RooGaussian *gaus = new RooGaussian(“gaus”,“gaus”,*obs_var,*mean,*sigma) ;

RooRealVar *step_value = new RooRealVar(“step_value”, “step value”,120.,110.,130.) ;
//RooGenericPdf *step_func = new RooGenericPdf(“step_func”,“step_func”,“(abs(step_value-obs_var)/(step_value-obs_var)+1.0)/2.0”,RooArgSet(*obs_var,*step_value));
RooGenericPdf *step_func = new RooGenericPdf(“step_func”,“step_func”,"((abs( @ 0- @ 1)/(@ 0-@ 1)+1.0)/2.0)*@ 2",RooArgSet(*obs_var,*step_value,*exp));
//RooProdPdf *step_gen = new RooProdPdf(“model”, “model”, RooArgSet(*step_func,*exp));
RooFFTConvPdf *exp_gaus = new RooFFTConvPdf(“exp_gaus”,“exp_gaus”, *obs_var, *gaus, *step_func);
RooPlot *frame = obs_var->frame() ;
exp_gaus->plotOn(frame);
frame->Draw() ;

}

Hi @zebing_wang,

I will invite @moneta and @jonas to this topic as our RooFit experts.

Cheers,
J.

Thanks!

Hi @zebing_wang,

first of all, just FYI, your code is full of memory leaks. If you create new objects with new, you also have to delete them unless another object takes ownership of them. This is not the case here, and it’s better to create all objects on the stack:

void test() {
  using namespace RooFit;

  RooRealVar obs_var{"obs_var", "obs_var", 120, 110, 180};

  RooRealVar tau{"tau", "tau", -0.02, -10, -0.};
  RooExponential exp{"model", "model", obs_var, tau};
  RooRealVar mean{"mean", "mean", 10, 0, 180};
  RooRealVar sigma{"sigma", "sigma", 20, -10, 20};
  RooGaussian gaus{"gaus", "gaus", obs_var, mean, sigma};

  RooRealVar step_value{"step_value", "step value", 120., 110., 130.};
  // RooGenericPdf step_func("step_func",
  //                         "(abs(step_value-obs_var)/(step_value-obs_var)+1.0)/2.0",
  //                         {obs_var, step_value});
  RooGenericPdf step_func{
      "step_func", "( @0 > @1) * @2", {obs_var, step_value, exp}};
  // RooProdPdf step_gen{"model", "model", {step_func,exp}};
  RooFFTConvPdf exp_gaus{
      "exp_gaus", "exp_gaus", obs_var, gaus, step_func};

  RooPlot *frame = obs_var.frame();
  gaus.plotOn(frame, LineColor(kBlue));
  step_func.plotOn(frame, LineColor(kRed));
  exp_gaus.plotOn(frame, LineColor(kGreen));
  frame->Draw();
}

Then, as for why the convolution doesn’t work, it’s just that the range for your obs_var is too narrow to include the bulk of the Gaussian pdf. So what happened is that the convolution was only done with the small part of the Gaussian that was defined above x > 110, and that convolution is mathematically only non-zero above 230 (adding the step_value as a lower bound for the other pdf that is in the convolution). If you widen the definition range of obs_var a bit, you can see the convolution:

RooRealVar obs_var{"obs_var", "obs_var", 120, -100, 500};

I hope this helps!

Jonas

Hi,

I see, it works now, thanks for your explain!

Zebing

But my fit range is [110, 180] GeV, is there any possible to use the same range? The convolution works without the step function, but once I add the step function, it will be failed. Do you have any solution about this?

Thanks!

Sure! You can always define a separate fit range for your observable and pass it to fitTo with the Range() parameter. You can look at this tutorial to see how it is done:
https://root.cern/doc/master/rf203__ranges_8C.html

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