Image quality issue when saving TH2D's drawn with colz option as a PDF

When I draw a bunch of TH2D histograms with “colz” option on different pads of a canvas and save the canvas as a pdf and a png file, plots on the pdf file look weird. Colors get blended between adjacent bins and empty bins are treated unequally. See the blue and white strips between X=[-40, -20] for example. They don’t have equal width. It is better on the png in this regard, but it has problems too. When I view the histograms with TBrowser, everything looks fine.

Attaching a reproducer macro.

What is the solution for improving image quality in pdf ?


fill_TH2D.C (2.3 KB)


_ROOT Version: 6.32.00
Platform: Ubuntu 22.04 LTS
Compiler: gcc (conda-forge gcc 12.3.0-13) 12.3.0


I think you have it backwards; running your macro, the problem is not in the PDF (the top image in your post), but in the PNG file (bottom image). A PNG is a raster image, i.e. composed by pixels, and in your case there are just not enough pixels for the number of bins in all the plots in the canvas, so some rows/columns get squished, resulting in artifacts. To avoid that, you need a bigger canvas (or make each plot in a separate canvas and PNG file, also big enough, and then outside ROOT join the images -without resizing- into a bigger one), or use histograms with fewer bins.

I tried to increase the canvas resolution by 2 and 4, pdf artifact did not disappear. Why would that be ?

   TCanvas *c1 = new TCanvas("c1", "3x3 Canvas with Histograms", 1800, 900);
   c1->SetCanvasSize(3000, 2800);

Try adding

gStyle->SetLineScalePS(1);

In your macro.

Unfortunately none of these options worked for me when drawing multiple histograms on the same canvas and when saving to a pdf. Increasing the canvas size increases the image quality for png but not for pdf. I think there is no option other than drawing and saving one plot at a time and then merging them later, which will make life not easier.

I don’t see any uneven spaces on the PDF file. Maybe you mean the page size is too small? You can enlarge it as much as you need and it should look fine, as I think ROOT creates the plots with vector elements. Anyway, if you want a larger page size in the PDF, one way is with these steps:

  1. Set a larger paper size, e.g.
         gStyle->SetPaperSize(50,50);    // in cm; defaults are 20,26
  1. Save as EPS (not PDF)
	c1->SaveAs("th2d_histogram.eps");
  1. Convert (outside ROOT) the EPS to PDF with ps2pdf; since the EPS contains a bounding box, the page size can be preserved with the option -dEPSCrop:
$   ps2pdf -dEPSCrop th2d_histogram.eps

(without the option, the canvas is cropped to fit your system’s default page size, probably A4 or letter).

for me also when I add SetLineScalePS the two plots PDF and png look the same.

@dastudillo @couet
Can I kindly ask you to attach here or somewhere else the PDF output that you get when you run the macro I provided after putting in your modifications ? I want to make sure we are talking about the same thing.

fill_TH2D.C (2.4 KB)
th2d_histogram.pdf (304.7 KB)

Are you referring to the “stroke” of the color boxes that makes the height of the white gaps (strips) look smaller in height than the blue bins (boxes)?

See related discussion: Colored 2D histograms in pdf output - #52 by couet

A workaround might be to define a slightly transparent color palette, so that stroke is removed.

Yes, that was one of my main points. White strips being thinner than colored strips.
And I didn’t know that was a known issue since 2012. Now I need to go through that topic with 50 messages long to have an understanding of what’s going on. I attached two screenshots I took when viewing @couet 's PDF output at 1600% magnification on Okular viewer.


Yep, then try the workaround of defining your Palette with 99% opacity, that should fix it I believe.
TColor::CreateGradientTable…

Here’s my PDF using my suggestions

//...
  gStyle->SetPaperSize(50,50);
  TCanvas *c1 = new TCanvas("c1", "3x3 Canvas with Histograms", 1800, 900);
  c1->SetCanvasSize(3000, 2800);
//...
  c1->SaveAs("th2d_histogram.eps");
//...

and ps2pdf -dEPSCrop th2d_histogram.eps

th2d_histogram.pdf (424.1 KB)

And this is at the max zoom level I get on Xreader (doesn’t say the %):
image
And on Brave browser I can go to 500%:

Another workaround is to use Latex output as suggested in the long-post-link above, then with lualatex you will get also the right gaps.

I zoomed to the maximum I could my pdf file on Mac using “preview” and I do not see any problem.

Well, @dastudillo’s suggestion works up to a degree, but not perfect. I can still see what you call the strokes when zoomed in 1600% in Okular.
@ferhue 's latex suggestion, pdftex or pdflatex conversion did not work in my setup despite the fact that the packages are installed.
@couet All of these can be due to buggy pdf viewers but I switched to Windows just to see how Acrobat Reader shows the plots and I could still see the strokes.

In any way, I would prefer a direct pdf output, rather than two-step process with ps2pdf or pdflatex.

Upon suggestion of @ferhue about defining a color palette with 99% opacity, in my original macro, when I add the following lines,

    // Number of colors in the palette
    Int_t nColors = 50;
    Int_t palette[nColors];

    // Define a custom color palette
    for (Int_t i = 0; i < nColors; i++) {
        Double_t red = (Double_t)i / (nColors - 1);   // Gradient in red
        Double_t green = 1 - red;                     // Gradient in green
        Double_t blue = 0.5;                          // Fixed blue value
        Double_t alpha = 0.99;                        // Transparency at 99%

        // Create a new TColor for each palette entry
        TColor *color = new TColor(5000 + i, red, green, blue, "", alpha); // Indices start at 5000+
        palette[i] = 5000 + i;  // Assign the color index
    }

    // Set the palette to the histogram
    gStyle->SetPalette(nColors, palette);
    gStyle->SetLineScalePS(1);

I get an output I’d be ok if the color palette were still kBird. But it gets broken. (See attachment)

Do you know an easy workaround that would restore a kBird looking palette ?

th2d_histogram.pdf (247.7 KB)

Try with gStyle->SetPalette(kBird,nullptr,0.99), then it will work.

Regarding Latex output, it will work if you try instead with lualatex. But I just noticed that in the TEX output the artefacts are still there even with transparent palette. A workaround is just find+replace \draw [color=c, fill=c, fill opacity=0.99] with \fill [c, fill opacity=0.99]. I’ve filed [graf2d] mimick TPDF behavior with box strokes also in TLatex by ferdymercury · Pull Request #17203 · root-project/root · GitHub