Is it possible to include fit parameters in a TLegend in a nice looking way?

Hello,

I am wondering if it is possible to create one single legend for a graph with a fit function, where the legend contains the markers and the fit function line (with their respective descriptions) PLUS the fit parameters of the function.
I’ve tried creating a TLegend for the graph and the fit function and also setting gStyle->SetOptFit(1111) separately, but getting the two boxes to align nicely is a lot of inconvenient fiddling around, especially if the fonts should be the same size, the alignment should be nice etc. So I am wondering, is there a (more or less) straightforward way of including the fit parameters in the TLegend (or an alternative to TLegend that can accomplish this)?

This is my code at the moment:

{
  TCanvas *myCanvas = new TCanvas("myCanvas","Window1", 1080,720);
  myCanvas -> SetGrid();

  TGraph *gr1 = new TGraph("data.txt");
  gr1 -> SetTitle("Autocorrelation fit function for 138#pm 3 kcts/s;#Delta t [ns];Counts");
  gr1 -> SetMarkerStyle(22);
  gr1 -> SetMarkerSize(1);
  gr1 -> SetMarkerColor(kBlue);
  gr1 -> GetXaxis() -> SetLimits(0,2400);

  TF1 *fitfunc = new TF1("fitfunc","[0]*(1-([1]+1)*exp(-[2]*abs(x-[3]))+[1]*exp(-[4]*abs(x-[3])))+[5]",0,2400);
  fitfunc -> SetParameters(738,0.49,0.079,2269,0.0086,100);
  fitfunc -> SetParNames("C_{1}","k","k_{1}","x_{0}","k_{2}","C_{0}");
  
  gr1 -> Fit(fitfunc,"R0");

  fitfunc -> SetLineColor(kBlue+2);
  fitfunc -> SetLineWidth(4);

  TLegend *leg = new TLegend(0.11,0.75,0.5,0.89);
  leg -> AddEntry(gr1, "Measured counts", "P");
  leg -> AddEntry(fitfunc, "Fit function", "L");
  leg -> SetBorderSize(1);

  
  // What follows is the option that I am currently using. It sort of gets everything to align on my screen, but seems rather inconvenient:
  gStyle -> SetOptFit(1111);
  gStyle -> SetStatBorderSize(1);
  gStyle -> SetStatX(0.5);
  gStyle -> SetStatY(0.75);
  gStyle -> SetStatW(0.2165);
  
  gr1 -> Draw("AP");
  fitfunc -> Draw("same");
  leg -> Draw("same");
}

My Idea was to include the fit parameters in the TLegend in some way like the following (replacing the entire gStyle section above):

for(int par=0;par<=5;par++){
     leg -> AddEntry(fitfunc->GetParName(par), Form("%g",fitfunc->GetParameter(par))," ");
  }

This displays the parameter values nicely; however it does NOT display the parameter names and I also don’t have any ideas on how I would add the errors.

Thanks in advance!
Joscha

ROOT Version: v6.20.04
Platform: Ubuntu 20.04
Compiler: Cling


You can type the text you want to show in the legend: Form("Value of par is = %g",fitfunc->GetParameter(par)... and so on.
To access fit results, read the Fitting Histograms section of the User’s guide.

Thanks for your reply!
I have managed to access the parameters as well as their names; the problem I can’t find a solution for is how to add the parameter names to the “Object” column of the legend. Meaning the parameter Names should be in the same legend column as the representations of the markers from gr1 and the function line from testfunc.
Since AddEntry needs a pointer to some form of TObject as its first argument, I’ve tried

TObjString *par0Name = new TObjString("Value for Par0: "); 
leg -> AddEntry(par0Name, Form("%g",fitfunc->GetParameter(0))," ");

This runs without any errors or warnings and prints the VALUE of the parameter where I want it (though I still need to figure out how to add the errors). But the name of the Parameter doesn’t show up, no matter which options I use for AddEntry.
Is it possible at all to add an object to the left column of the legend (in a visible way) if it’s not a TAttLine, TAttMarker or TAttFill Object?

To add a entry in a Legend you need to have an object to be added.

Does par0Name in my example above not count as an object? Or does the object have to be of the TAttLine, TAttMarker or TAttFill kind?

Of course the object must inherit from TAttLine , TAttMarker or TAttFill… otherwise how can you find the graphics attributes ?

I am not sure using TLgend to draw fit parameters is a good idea anyway. Legend is very specific … and fit parameters do not have any graphical attributes. If you are not happy with the default display of fit parameters and cannot tune it the way you need, you will have to draw them yourself using TLatex for instance.

Of course the object must inherit from TAttLine , TAttMarker or TAttFill … otherwise how can you find the graphics attributes ?

That makes sense, thank you.
There is one last idea that I just thought of: Is it possible to create a custom TAttMarker (that consists of the name of the respective parameter) and put that in the object column (with a reasonable amout of work)?
Otherwise I am probably going to go with other options.

That sounds much more work than making a macro which align the legend and the fit box.