python-ternary
python-ternary copied to clipboard
Heatmap polygon triangles don't meet exactly
Hey Marc,
Lovely library. I've used it to make some great heatmaps from a data dictionary. Just thought I'd file a bug report as the triangles don't quite match up if you zoom in - its really noticeable if you remove gridlines and have a low scale.
Cheers, J.
Hi @JoshuaMeyers,
Thanks for the report. Can you post a screenshot/image, and if possible, a small data set that reproduces the issue?
Hey Marc,
Sorry that was a lazy report! Here is some simplified code and an example image. I have not included a dataset, any should recreate the issue.
If you zoom in on this image. You will see that the corners of the triangles do not meet each other.
Hope this is more helpful.
#PMI ternary density plot
#set up figure
figure, ax = plt.subplots()
tax = ternary.TernaryAxesSubplot(ax=ax, scale=scale)
plt.axis('off') #turn border off
figure.set_size_inches(15.3, 14)
tax.boundary(linewidth=1.5)
#make colormap with white zero value (or more accurately any value below vmin)
cmap_whiteZero = matplotlib.cm.get_cmap('Spectral_r')
cmap_whiteZero.set_under('w')
eps = np.spacing(0.0)
#plot ternary heatmap
tax.heatmap(log_dict, style="t", cmap=cmap_whiteZero, vmin=eps, colorbar=True) # style can be t, d, or h
# tax.gridlines(color="0.2", multiple=1, linewidth=0.8, linestyle='-') #uncomment for gridlines
figure.gca().invert_yaxis()
plt.savefig('/Users/jmeyers/Desktop/myfig.pdf')
Thanks. Some of this is simply because of how matplotlib draws lines. I may be able to fix the corners. The other edge artifacts are because of the line width of the border -- the thickness of the border lines are covering up part of the corners of the interior colored trianges. This could be fixed by slightly moving the lines outward by the line-width. I'll have to think about how to do that for an arbitrary scale factor.
You might have better results in the meantime by setting the border to have smaller line-width.
As for the odd interior overlaps, I'll have to investigate cause -- I suspect it's something like rounding errors on the polygon coordinates.
This could be related to this matplotlib error: https://github.com/matplotlib/matplotlib/issues/2935
I was able to fix the overlap of the triangles in the interior by replacing https://github.com/marcharper/python-ternary/blob/master/ternary/heatmapping.py#L260
ax.fill(xs, ys, facecolor=color, edgecolor=color)
with
ax.fill(xs, ys, facecolor=color, edgecolor=color, linewidth=0.01)
I think the problem is, that the linewidth
is too thick and this leads to a large overlap and misalignment of the triangles.
Setting the linewidth
to 0.0
is however also not a good idea, because then a small white boundary is visible between the triangles.
At least for my small toy example setting the linewidth
fixed the problem.
I was able to fix the overlap of the triangles in the interior by replacing https://github.com/marcharper/python-ternary/blob/master/ternary/heatmapping.py#L260
ax.fill(xs, ys, facecolor=color, edgecolor=color)
with
ax.fill(xs, ys, facecolor=color, edgecolor=color, linewidth=0.01)
I think the problem is, that the
linewidth
is too thick and this leads to a large overlap and misalignment of the triangles. Setting thelinewidth
to0.0
is however also not a good idea, because then a small white boundary is visible between the triangles.At least for my small toy example setting the
linewidth
fixed the problem.
Setting edgecolor=None
without a linewidth
argument does not result in any whitespace for me. Might be worth trying that. FWIW I'm using matplotlib ver. 3.2.2.
ax.fill(xs, ys, facecolor=color, edgecolor=None)
It's also worth noting that this also solves an issue that I encountered when trying to resize the PDF version of this plot in Adobe Illustrator. Illustrator does not resize lines by default but does resize shapes. So when you shrink the ternary heatmap, the stroke widths on the lines stay the same; exacerbating the non-overlapping shapes issue.
Zoomed-in shrunk in Illustrator example w/o any changes:
Zoomed-in shrunk in Illustrator example w/ edgecolor=None
: