-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated method for ternary contour figure factory #1418
Conversation
Looks very promising!! Would definitely prefer this approach using the ternary axis system. |
Thanks for giving this a go @emmanuelle! This looks really nice. Here's an example of laying the grid of points over the contours (grabbed this example from one of the tests) import numpy as np
from plotly.graph_objs import graph_objs as go
import plotly.figure_factory as ff
a, b = np.mgrid[0:1:20j, 0:1:20j]
mask = a + b < 1.
a = a[mask].ravel()
b = b[mask].ravel()
c = 1 - a - b
z = a * b * c
fig = go.FigureWidget(ff.create_ternarycontour(np.stack((a, b, c)), z, colorscale='Greens'))
fig fig.add_scatterternary(a=a, b=b, c=c, mode='markers', marker={'color': z});
fig This works great! Although it looks like the contours may be a little off center. Here's what I'm thinking we would need for an initial release
If it makes things simpler to deal with for v1, we can just start with supporting only the named colorscales. We can add support for custom colorscales later on. How does that sound? Regarding the contour calculation approach, it looks like ggterm supports two methods (See "Use of Orthonormal Basis" in http://www.ggtern.com/2016/01/17/ggtern-2-0-now-available/). So it make sense to me to eventually support multiple here as well. But we could ship the first revision with whichever reasonable approach we're closest to having done. |
@jonmmease @jackparmer thanks for the comments and suggestions, I'll be working on it. What do you think about a scikit-image dependency? At the moment, |
For the question of whether we also want this figure factory to support computing the kernel density directly from a collection of input points in Barycentric coordinates, we could keep the same API with |
@emmanuelle, @jonmmease The orthonormal basis in ggtern means using the ilr-transformation. From references I read it follows that the ilr-transformation and its inverse are better than the transformation from barycentric to cartesian and back, because ilr preserves the distances, and angles. That's why the statistics of compositional data is now based on ilr-transformation. The barycentric-to-cartesian- and back to barycentric was the method used in ggtern in its first versions. It is still there as a second option. All plots on the ggtern site, for the last versions are performed with ilr-transformation. |
Hi @emmanuelle ,
In terms of dependencies, we've tried to keep the core of plotly.py needing as few dependencies as possible, but the figure factories have lots of optional dependencies and there's no problem with adding scikit-image / matplotlib as additional ones. See
I'm leaning towards a second function name because I can imagine wanting to add some additional arguments that are only relevant in the KDE case. For example @empet, thanks for all of the background research on this. Yeah, it does look like the ilr transform approach is the right way to do this in the long run. |
Here's what I'm thinking. Since we probably need a few more days on this, I'll go ahead and merge #1413 and call it a preview of ternary contour support in the release notes. Then we keep working on this PR for the next release. |
Still WIP, with some additions:
Remains to be done:
Stylistic question: what is the policy of plotly regarding names of keyword arguments, whether to use underscores or not? (eg And a maths question for @empet: in ILR mode, is it ok when no data are available for the poles of the triangle? I had the impression that the function behaved better when the poles of the triangle belong to the set of data points. I'll post a notebook later on to show some examples. |
The "deep" colormap used by @empet to visualize filled contours looks really good (https://nbviewer.jupyter.org/github/empet/Ternary-contour-plot/blob/master/Plotly-ternary-contour-plot.ipynb), is it ok if I add it to Plotly colorscales in |
The ilr transformation maps the open triangle (i.e. without its boundaries) to the 2d-space. It is an isomorphism. The closed simplex cannot be mapped continuously on all 2d-space, by a one-to-one map. The ilr trasnformation was introduced because the classical statistics works As I stressed before, the ilr preserves distances and angles and so the statistical info associated to the ilr-transformed data is mapped back to the simplex, via the inverse ilr-transformation, without deformation. On the other hand, if we have a pdf concentrated on the simplex, the probability to select/generate data on the simplex sides is zero, i.e. the integral of that density on the sides is 0. All drawbacks you outlined above, when working with ilr-transformation, manifest only because you don't define a real plotly contour. The |
Wow, this is awesome @emmanuelle! Thanks for sticking with it 🙂 Just let me know when you're ready for me to take another look. |
Looks amazing!!
…On Wed, Feb 6, 2019 at 6:37 PM Jon Mease ***@***.***> wrote:
Wow, this is awesome @emmanuelle <https://github.com/emmanuelle>! Thanks
for sticking with it 🙂 Just let me know when you're ready for me to take
another look.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1418 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABx4ashn0VCf1PxFpQOtoaOZXCIsrbqhks5vK2cugaJpZM4adQf4>
.
|
OK, so I think I made it work finally. It's been quite hard to find a way to handle boundaries correctly (setting values outside the valid range of ternary values before computing contours and setting correctly a background color), but now I'm happy with all the examples I tried. The notebook which I have been using for testing is this one https://plot.ly/~emmanuelle/54 @jonmmease ready for a review! |
Thank you so much - looks really, really great. The only major issue I saw is the hover. One hack around this is to turn off hover for all traces, then add a transparent trace (opacity = 0) of scatter points where hover is turned on. |
Yes, I did not understand why the hover is different when the trace is displayed as lines or as filled contours... |
These examples look awesome @emmanuelle! I'll take another look over the code soon, and we can get this in for 3.7.0. |
Finally had a chance to dig in here, and I'm really excited to have this in plotly.py! Here are some notes and suggestions. 1)
|
Thank you @jonmmease for the detailed review. I'm quite busy at the moment with other projects (webinar coming next Wednesday), can this wait a few days or is 3.7.0 due soon? |
Thanks for the update @emmanuelle, no problem. plotly.js 1.45.0 came out yesterday so I'd like wait and see if there will be a 1.45.1 soon, and release 3.7.0 in a week or so. Does that sound workable for you? |
yes! |
@jonmmease there you go! I addressed all points, hope it's OK! |
This gives consistent behavior between fill and lines modes
Looks great! Thanks for making all of these updates @emmanuelle. I made a few more small updates and I'm really happy with how everything turned out. I'll merge this in when the tests are green. |
💃 🎉 |
Awesome! Thanks a lot @jonmmease I learnt a lot of things while working on this PR! |
Following the suggestions in #1413, and help from @empet, here is an alternative version for implementing contour plots in ternary diagrams.
Pros: this method uses a ScatterTernary trace, meaning that it is natively an object of a ternary plot, hence it uses the ternary pan/zoom.
Cons: the trace is not a Contour trace, hence quite a lot of boilerplate code will be needed for handling colorscale, colorbar, etc.
I post here a first proof of concept, the PR is far from being finished (TODO: fix tests, fix documentation, implement annotations better etc.).
@empet: I haven't had the time yet to compare this method with yours using ILR transform, but I'll surely do!