What I want to achieve
The framework ROOT can create 2D histogram plots with colored boxes indicating count rate that looks something like:
My question is really only: can I produce this kind of 2D histogram through PGFPlots? The rest of this post describes my current findings and attempts.
As of writing quite recently, ROOT got a TikZ output engine called TTeXDump
, that in turn would generate:
This is closing in on good graphical quality. The axis label texts are easily manually modified to TeX syntax (or it could be done in ROOT before the export), but there are other issues:
- Placement of labels, ticks, etc., are all done by raw coordinates (sample TikZ code output from
TTeXDump
describing the above image). To e.g. center thex
label below the axis is thus not trivial, which makes it tricky to conform to a graphical layout that coincides with other plots made directly with PGFPlots. - Since all graphical entities are statically defined, scaling will not yield transparent results.
and probably other things.
Own attempts
I have made some attempts at generating the plot with PGFPlots from exported ROOT data. There are, however, several details that I do not get right, and perhaps there is a more obvious solution.
By dumping the histogram bin data in the form
xcenter ycenter weight
in the file scatter.csv
(Pastebin link of data), the following code gives the below result:
\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{siunitx}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xlabel={$\theta$ /($\pi$ rad)},
ylabel={Energy /\si{\MeV}},
enlarge x limits=.02,
enlarge y limits=.02,
minor tick num=4,
xticklabel style={/pgf/number format/fixed},% exponential axis notation looks bad in this case
colorbar,
scatter/use mapped color={%
draw=mapped color,
fill=mapped color
}]
\addplot[
scatter,
scatter src=explicit,
only marks,
mark=square*,
] file{scatter.csv};
\end{axis}
\end{tikzpicture}
\end{document}
Fine-tuning of text, tick marks, colormap, etc., is easily done after this, but there are some issues with the data rendering:
- The "bin" dimensions are emulated by the marker size, but it would be nice to input the bin numbers directly to set the marker sizes. This would also need to be done asymmetrically, since there will be a different amount of bins in the
x
andy
direction. I have looked atmark=cube*
withcube/size x
andcube/size y
, but have not successfully been able to change the mark dimensions. Currently, the marks are symmetric, which might look alright at a quick glance, but actually marks overlap in non-trivial ways and it is a deal breaker in itself. - The
enlarge x axis
andenlarge y axis
values are inserted after inspection, to avoid the marks from protruding outside the axis. Rather, the axis distance should be automatically calculated from the marker size. - The data point markers are on top of the axis and tick marks, which is not optimal here. Force “axis on top” for plotmarks in pgfplots has some info on this, with somewhat convoluted solutions. Is there an even better way to be found here?
Is the scatter plot approach taken above perhaps the wrong one? Some other thoughts have been:
- Perhaps I could use the scatter plot data directly and perform the binning with PGFPlots instead of exporting calculated bins. I can not find a way to do this though, and there is a potential risk of running into the memory limit.
The initial ROOT output PDF could be stripped of axis, tick marks and titles, keeping only the graph surface. Then I could use
\addplot figure
to include this and paint the axis back on with PGFPlots. Numerical axis limits could be extracted from ROOT, so the scale should be able to be correctly reproduced. I have not looked into calibrating the colormap scale in PGFPlots from max/min values, but that should also be possible. There would perhaps be some alignment issues to solve.It would help automation if I could use the
TTeXDump
output, strip the statically defined axis, ticks, etc., and just use the generated TikZ commands for painting the graph body. I can not see a trivial way to combine this with\addplot
though.The data output could have been defined in bin numbers instead of explicit coordinates, i.e.
1 10 11.0
for
x
bin 1,y
bin 10 with value 11, instead of the current:0.04580479262184749 0.0755985979686503 11.0
Since we also have the axis limits and bin amounts defined, this should really be all the info we need to build the histogram, but I do not find it to be trivial to perform.
Conclusion
That might seem like a lot of questions, but as mentioned initially, the kernel is really only a single one: can I produce this kind of 2D histogram through PGFPlots?
surf
visualization which avoids overlaps. That linked question is about the fact that you want to assign cdata to the whole bin, not to a corner (and provides a workaround to get that, no real solution). If you do not have matrix form,scatter
is a good choice.axis
(with correct alignment and scaling).cube/size x
in a 2d axis is probably a bug.mark=cube
is only available for 3d axes, it falls back tomark=square
for 2dTTeXDump
in ROOT. Thanks again!