python-ternary
python-ternary copied to clipboard
heatmap(density) from scattered dots?
Hi~ I'm wondering whether there is a easy way to plot "density" from pure dots? So I'm able to make a scatter plot from dots but what I would like to have is to get a density heat map. But from my understanding, the current heat map function needs a dictionary feed in.
Thanks a lot!
There's no built in function like matplotlib provides. The easiest way is to write an interpolation function and use heatmapf
or to compute your own dictionary.
I have tried to compute a 3D histogram based on scatter data of the format [0, 0.8, 0.2], [0.3, 0.4 ,0.3] etc.. I then smooth this histogram with a Gaussian kernel. I finally create a dictionary of the smoothed histogram pointing to each coordinate e.g. (0, 0, 0), (0, 0, 1) ... (1, 1, 1) to be mapped to the simplex space.
xyz = np.loadtxt('data.txt', delimiter=',')
nbins = 11
import numpy as np
H, b = np.histogramdd((xyz[:, 0], xyz[:, 1], xyz[:, 2]),
bins=(nbins, nbins, nbins), range=((0, 1), (0, 1), (0, 1)))
H = H / np.sum(H)
# 3D smoothing and interpolation
from scipy.ndimage.filters import gaussian_filter
kde = gaussian_filter(H, sigma=2)
interp_dict = dict()
binx = np.linspace(0, 1, nbins)
for i, x in enumerate(binx):
for j, y in enumerate(binx):
for k, z in enumerate(binx):
interp_dict[(i/10, j/10, k/10)] = kde[i, j, k]
fig, tax = ternary.figure(scale=1)
tax.heatmap(interp_dict)
tax.show()
I've attached my result. I'm not entirely too sure what is going on and whether I am calling the scale
variable correctly. My understanding was that if scale=1
, (i, j, k)
had to sum to 1. However, looking at the heatmap example here, the x
that is passed to the heatmap function f
sum to 1
and not 10
.
Any help would be appreciate @marcharper and thanks again for a beautiful package :)
For heatmaps i + j + k = scale
. These functions create a partition of the simplex and color each sub-polygon (triangles or hexagons) with the lattice point value. The scale
parameter is how it defines the lattice.
I think you can simply scale up your points -- for scale = 1
there's only one subtriangle (0, 0, 1)
, hence the monocolor plot. Try scale = 10
and interp_dict[(i, j, k)] = kde[i, j, k]
.
Yup! Works perfectly - see below.
Thanks again - your package is really helping my upcoming paper submissions
Glad to hear it! Let me know when you get published and I'll add your paper to the citations page.
From here, is there a way to scale back the labels on the axis so they go between 0 and 1?
Yes, you can directly overwrite the axes' values using matplotlib's functions for the outer plot (the usual x-axis and y-axis), or the analogous ternary functions if you are using the ternary axes markings on the three triangle sides. See the example here for the matplotlib case.
This was a very useful piece of code, I think it would be great if it would be part of the ternary codebase!
+1 to this! Supremely helpful, and definitely something that would be a nice addition if possible!
This was a very useful piece of code, I think it would be great if it would be part of the ternary codebase!