Error in <THistPainter::PaintInit>: log scale requested with a negative argument (-0.141557)

Dear experts

I want to calculate the time cost for two different algorithms for convolution, then I draw them on a TMultiGraph which contains 2 TGraph inside. I confirmed every point is positive x and y, but I got the error when I try to TCanvas::SetLogx() and TCanvas::SetLogy(), why?

I attach my working example here:
checkTimeCostFFT.cxx (4.7 KB)
graph.root (6.9 KB)

And the output of values says they are all positive:

0th loop finished with inputLength = 1
    normal convolution time cost: 2.625e-06
    FFT    convolution time cost: 0.391761
1th loop finished with inputLength = 4
    normal convolution time cost: 9.417e-06
    FFT    convolution time cost: 0.662822
2th loop finished with inputLength = 16
    normal convolution time cost: 6.8792e-05
    FFT    convolution time cost: 1.12083
3th loop finished with inputLength = 64
    normal convolution time cost: 0.000505083
    FFT    convolution time cost: 1.80859
4th loop finished with inputLength = 256
    normal convolution time cost: 0.00397829
    FFT    convolution time cost: 2.83119

ROOT version: 6.32.08

I’ll check

I am missing the file graph.root.

Oh, sorry for that, now I uploaded the graph.root

And I confirmed that this error is from SetLogy(), not SetLogx()

The painting method of TMultigraph keeps a margin of 0.0001 of the y range to avoid the graphs’ points overlap the Y axis. In your case this value is too big and the minimum of the axis becomes negative. You can bypass this problem with some code like:

    TMultiGraph* g_time = new TMultiGraph();
    g_time->Add(g_normal);
    g_time->Add(g_FFT);
    
    g_time->GetXaxis()->SetTitle("Input vector length");
    g_time->GetYaxis()->SetTitle("Time cost [s]");
    printf("g_time minimum = %g\n",g_time->GetHistogram()->GetMinimum()); // shows the axis minimum is < 0
    g_time->SetMinimum(0.000001); // define a positive minimum
    c->SetLogx();
    c->SetLogy();

    g_time->Draw("AP")

Thank you, this fixed the problem, but I found if I change the loop to 10 then only the last 4 points are shown, can you please have a look?
checkTimeCostFFT.cxx (5.0 KB)

I am looking at it

Actually the points are there you will see them if you suppress the log scale along X. I think we are facing the same issue we saw with log Y . All your values along X and Y are positive so the alogorithm computing the limit should be able to generate proper positive scales automalically. Give me a bit of time and I’ll comme with a fix.

At the end of you macro I printed the two graphs and made a simpler macro with these values. I thought I will get the same errors but surpreingly I get a correct plot even without setting the Y minium. The macro is the following. May be you can try it.

{
   auto g1 = new TGraph();
   g1->SetMarkerStyle(20);
   g1->SetMarkerColor(kBlue);
   g1->AddPoint( 1,      3e-06);
   g1->AddPoint( 4,      7.25e-06);
   g1->AddPoint( 16,     5.6458e-05);
   g1->AddPoint( 64,     0.000358042);
   g1->AddPoint( 256,    0.00288179);
   g1->AddPoint( 1024,   0.0232125);
   g1->AddPoint( 4096,   0.181971);
   g1->AddPoint( 16384,  1.47276);
   g1->AddPoint( 65536,  23.9272);
   g1->AddPoint( 262144, 393.396);
   
   auto g2 = new TGraph();
   g2->SetMarkerStyle(21);
   g2->SetMarkerColor(kRed);
   g2->AddPoint( 1,      0.310709);
   g2->AddPoint( 4,      0.534144);
   g2->AddPoint( 16,     0.892891);
   g2->AddPoint( 64,     1.45679);
   g2->AddPoint( 256,    2.29943);
   g2->AddPoint( 1024,   3.49948);
   g2->AddPoint( 4096,   5.42755);
   g2->AddPoint( 16384,  11.2071);
   g2->AddPoint( 65536,  20.767);
   g2->AddPoint( 262144, 35.4994);
   
   auto c = new TCanvas();
   c->SetLogx();
   c->SetLogy();
   auto gm = new TMultiGraph();
   gm->Add(g1);
   gm->Add(g2);
   gm->Draw("AP");
}

So it seems there is more than simply the grpahics part of root involved.

I found the culprit. If, in my previous example you, do:

   auto c = new TCanvas();
   auto gm = new TMultiGraph();
   gm->GetXaxis()->SetTitle("Input vector length");
   gm->GetYaxis()->SetTitle("Time cost [s]");
   c->SetLogx();
   c->SetLogy();
   gm->Add(g1);
   gm->Add(g2);
   gm->Draw("AP");

then it cashes like in you example.
But if you set the titles after the 2 “Add” then it works.

   auto gm = new TMultiGraph();
   c->SetLogx();
   c->SetLogy();
   gm->Add(g1);
   gm->Add(g2);
   gm->GetXaxis()->SetTitle("Input vector length");
   gm->GetYaxis()->SetTitle("Time cost [s]");
   gm->Draw("AP");

It is because when you set the titles GetHistogram is called which creates the internal histogram fHistogram which hold the axis. But the real limits cannot be computed correctly as the Multigraph has no data yet. I will investigate how this can be improved.

Indeed the documentation of TMultiGraph::GetXaxis (and GetYaxis), already mentionned that.

This works for me, thanks a lot!

Indeed this is described in the class documentation, but setting titles before graph been drawn works if I used TGraph, so I expected it also work in TMultiGraph

TMultigraph is a collection of TGraph. The number of TGraphs in a TMultigraph is not limited. You can add as many as you want. Therefore the axis of a TMultigraph can be computed only at painting time, and are not defined before that.