Warning from TLegend and how to solve it

Hello everyone,

I am using ROOT’s graphics libraries for my C++ application. Now, to create a legend for the plot, I am using TLegend. It works fine and I have a nice legend on my plot but when I execute the program, I get the following warning:

Warning in <TLegend::Paint>: Legend too large to be automatically placed; a default position is used

Note that this warning is not thrown when I make. Now, I am okay with the warnings, but the problem is that TLegend is taking too long (~5 seconds) to decide where to put the TLegend box. Also, this complain from TLegend is fake as I only have 3 entries. Have a look at the plot below, there is nothing special

Now, I am happy with the default position as long as it does not take long for TLegend to decide. Is there anyway to tell TLegend to take the default position from the beginning?

Best,
Divyang.

Can you provide the code you use to create this (at least the relevant parts), or a minimal running reproducer?
Here is the relevant part of the TLegend source for the message you are seeing:

This message means that you are trying to let TLegend place itself automatically on the plot. The algorithm attempts to find some free space on the plot without hiding any graphics, and when it fails, it produces this message.

The solution is to place the legend yourself at an appropriate position instead of letting TLegend determine the position automatically. See the TLegend documentation for more details (search “The legend can be placed automatically”).

Here is the minimal version: Test.zip (3.8 KB)

Please go to source/Profile_func.cc, where I am using TLegend. Comment line number 130 (leg->Draw("same");) to remove the warning message.

OS: Ubuntu 20.04.6 LTS x86_64
ROOT: 6.24/08
compiler: g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0

Thanks. I am looking

I get errors:

root [0] 
Processing Profile_func.cc...
input_line_9:2:2: error: no matching constructor for initialization of 'Profile_func'
 Profile_func() /* .x tries to invoke function `Profile_func` */
 ^
/Users/couet/Downloads/Test/source/Profile_func.cc:15:15: note: candidate constructor not viable: requires single argument 'E', but no arguments were provided
Profile_func::Profile_func(double E)
              ^            ~~~~~~~~

What is the procedure to run your test ?

Sorry for not providing the steps to run.

  1. Go to Test directory, where makefile and main.cc are located
  2. run make to create executable named test_4_leg
  3. ./test_4_leg to run

do:

  {
    can1->cd(1);
    auto leg = new TLegend(0.1,0.7,0.48,0.9);
...
    leg->Draw();
  }

this code will disable the automatic placement and should remove the warning.
note “same” is not a option for TLegend::Draw

If you don’t draw gr2 the warning (and the delay) goes too, so it looks like it is doing something that it shouldn’t. With a very simple graph there’s no problem:

 //...
    TGraph *gr2 = new TGraph();
/*
    for (size_t i=0; i<=Get_E().size(); i++)
    {
      double dmmy[1] = {Get_E()[i]};
      Add_sigm_pp(FitFunc4_sigm_pp(dmmy, fit_para) );
      gr2->AddPoint(Get_E()[i], Get_sigm_pp()[i]);
    }
*/
    gr2->AddPoint(200,2.3);
    gr2->SetMarkerStyle(47);
    gr2->SetMarkerSize(2);
    gr2->SetMarkerColor(kGreen);
    gr2->Draw("P");
    leg->AddEntry(gr2, "Prjctl enrgy");

    //! comment line below to remove the warning
    leg->Draw();
//...
}

With the following code, there is no delay an no message:

void Profile_func::Set_Vis_FitFuncs()
{
  //
  TCanvas *can1 = new TCanvas();
  can1->Divide(3,2);

  //-------------------------------------
  {
    can1->cd(1);
    auto leg = new TLegend(0.1,0.7,0.48,0.9);

    std::vector<double> x = Get_data_E();
    std::vector<double> y = Get_data_sigm_pp();

    TGraph *gr = new TGraph();
    for (std::size_t i=0; i<x.size(); i++) {gr->AddPoint(x[i], y[i]);}
    gr->SetMarkerStyle(21);
    gr->SetMarkerColor(kBlue);
    gr->SetMarkerSize(1.);
    gr->Draw("AP");
    leg->AddEntry(gr, "data");

    TF1 *fit = new TF1("fit", FitFunc4_sigm_pp, 35, 1005, 6);
    gr->Fit(fit, "QR+");
    leg->AddEntry(fit, "fit");

    double fit_para[6] = {fit->GetParameter(0), fit->GetParameter(1),
                          fit->GetParameter(2), fit->GetParameter(3),
                          fit->GetParameter(4), fit->GetParameter(5)};

    TGraph *gr2 = new TGraph();
    for (size_t i=0; i<=Get_E().size(); i++)
    {
      double dmmy[1] = {Get_E()[i]};
      Add_sigm_pp(FitFunc4_sigm_pp(dmmy, fit_para) );
      gr2->AddPoint(Get_E()[i], Get_sigm_pp()[i]);
    }
    gr2->SetMarkerStyle(47);
    gr2->SetMarkerSize(2);
    gr2->SetMarkerColor(kGreen);
    gr2->Draw("same P");
    leg->AddEntry(gr2, "Prjctl enrgy");

    leg->Draw();
    gPad->Update();
    gPad->Modified();
  }

}

adjust the legend position as you like …