Closed chebee7i closed 9 years ago
Sure this is fine, we'd just need to permute the indices. I think maybe 'brl' for bottom-right-left is better than xyz, since it's not necessarily obvious which side is y and which is z. Or maybe 012 or 123 with counter-clockwise being the default.
I updated the heatmap code in the alt-heatmap branch to allow (i,j,k) in the data dictionary, so this fits nicely with that.
Another approach is to just make sure that ternary uses the same convention throughout and provide a convenience function to the user to permute the indices if desired.
Yeah the permuting could be nice. I did notice that you updated it to take (i,j,k) which was something I was wanting too. So this is just my ignorance, but can you explain bottom-right-left to me? I think of a triangle, as shown in the images, and the corners are most naturally top, right, and left (going clockwise in that case). How should I think of "bottom"? Are you thinking of the edges when you say that? If anything, this just shows that users (including myself) come at ternary plots from many different perspectives.
Yeah I was thinking of edges of the triangle. The format "012" is convenient since it corresponds to the indices of the point, so I think I'll go with that.
Also supporting permutations throughout is probably fine as well, it's another thing that the TernaryAxesSubplot class can track and supply to the other functions.
I just want to make sure I've understood correctly:
0 == (1, 0, 0)
1 == (0, 1, 0)
2 == (0, 0, 1)
Now, the user needs to specify how those points map to corners of the simplex. As an example, if the corners are labeled: "left", "top", and "right". Then:
012 :
left == 0
top == 1
right == 2
021 :
left == 0
top == 2
right == 1
...
I'm proposing this as the default (for "012"):
Permuting the values of "012" will permute the order in which the values are projected, so "120" would produce this (note the colors of the points rotated clockwise with the coordinates, but the coordinate labels didn't change since I didn't permute them):
So "120" means plot (counterclockwise) the '1' coordinate along the bottom axis, the '2' coordinate along the right-hand axis, and the '0' coordinate along the left-hand axis.
Ahh, ok. Got it. I can work with that.
This is so amusing for me. We both plot in ternary coordinates all the time, but we definitely come at it from different perspectives. For me, it's more natural to think of the coordinate labels as being informative about distributions. So the coordinate label 003 will always correspond (after normalization) to where the distribution (0,0,1) will be plotted. In that sense, I prefer to rotate the coordinate labels, and choosing a coordinate system amounts assigning each peaked distribution to a corner. Active vs passive I suppose.
What you propose will work well for me. I will operate almost exclusively with 210 which, assuming I've not mixed this up, means that:
coordinate at index 2 appears along bottom axis (and distribution (0,0,1) is in bottom right corner) coordinate at index 1 appears along right-hand axis (and distribution (0,1,0) is in top corner) coordinate at index 0 appears along left-hand axis (and distribution (1,0,0) is bottom left corner).
FYI, here is ggtern. It additionally provides a clockwise/counterclockwise argument. And it looks like in geology, clockwise is fairly common.
I'm wondering if the API could be flexible enough to support both the axes and corner perspectives. Not sure what the best convention is...'tc, lc, rc, ba, la, ra' seems the least normative.
For example:
corners = {'T', 'L', 'R'}
axes = {'b', 'r', 'l'}
def coordinate_system(self, coords, clockwise=False):
"""Sets the coordinate system to use when plotting..."""
try:
spec = set(coords.keys())
except AttributeError:
# Assume coords is a string specifying the axes.
if clockwise:
keys = 'blr'
else:
keys = 'brl'
coords = dict(zip(keys, map(int, coords)))
spec = axes
if spec == corners:
# Remap to the axes specification.
...
elif spec != axes:
raise Exception("`coords` must specifies all corners or all axes.")
# Proceed using the axes specification along with the value of clockwise.
....
Here are some sample calls:
I've almost finished updating the code to take an arbitrary permutation in all the necessary functions (this required a number of changes, but it was an improvement overall). Now that this is in (will push shortly), it's just an API matter to support how the user specifies it, and supporting both does not seem difficult.
Specifically, I rewrote all the heatmap functions to actually call project_point
, and the ternary axes class will apply the permutation to anything that is called.
Ok I just pushed a branch called permutations
. It is likely that there are bugs still, and the documentation needs to be updated. Please take a look!
I'll put some thought into clockwise plotting. It would be nice to have feature parity with ggtern... there's a lot of work to be done.
So now that the coordinate systems are consistent, I'm closing this issue. I'll open another one for the clockwise issue.
The current heatmap code places 001 at the lower left, while
project_point
places 100 at the lower left. My thought was that these conventions should match just in case you want to scatter and color polygons on the same MPL axis.More generally, it might be nice if the user could specify which coordinate system to use when plotting. For an upright simplex, we can call the corners left, center, right. The user might designate which coordinate system to use by specifying one of:
{'xyz', 'yzx', 'zxy', 'xzy', 'zyx', 'yxz'}
. So for'xyz'
, x = (1, 0, 0) is assigned to the left corner, y = (0, 1, 0) to the center, and z = (0, 0, 1) to the right corner.'xyz'
is probably going to the preferred one almost always.