giotto-ai / giotto-tda

A high-performance topological machine learning toolbox in Python
https://giotto-ai.github.io/gtda-docs
Other
849 stars 174 forks source link

plot_point_cloud, and VR.plot can show figures on Jupiter Notebook, but not in standalone Python IDE console #387

Closed cyinbox closed 4 years ago

cyinbox commented 4 years ago

Describe the bug

To reproduce

Expected behavior

Actual behaviour

Versions

Additional context

ulupo commented 4 years ago

Hi @cyinbox, thanks for the interest! However, we need a little more detail to reproduce. For instance, I just ran this in a Python console session:

from gtda.plotting import plot_point_cloud
from gtda.homology import VietorisRipsPersistence
import numpy as np

X = np.random.random((5,2))
plot_point_cloud(X)

and then

X_reshaped = X[None, :, :]
VietorisRipsPersistence().fit_transform_plot(X_reshaped)

and as expected in each case I get a browser window/tab opened with the plot correctly displayed. This is what is expected from plotly so I cannot reproduce the issue.

All our plotting functions simply construct a plotly figure object and then call fig.show() where fig is a plotly figure object. Plotly documentation: https://plotly.com/python/

cyinbox commented 4 years ago

Hi @cyinbox, thanks for the interest! However, we need a little more detail to reproduce. For instance, I just ran this in a Python console session:

from gtda.plotting import plot_point_cloud
from gtda.homology import VietorisRipsPersistence
import numpy as np

X = np.random.random((5,2))
plot_point_cloud(X)

and then

X_reshaped = X[None, :, :]
VietorisRipsPersistence().fit_transform_plot(X_reshaped)

and as expected in each case I get a browser window/tab opened with the plot correctly displayed. This is what is expected from plotly so I cannot reproduce the issue.

All our plotting functions simply construct a plotly figure object and then call fig.show() where fig is a plotly figure object. Plotly documentation: https://plotly.com/python/

The figures can be rendered in a browser (Jupyter notebook), but not in a standalone IDE, for example, I use Spyder in Anaconda.

ulupo commented 4 years ago

@cyinbox thanks for the feedback.

The figures can be rendered in a browser (Jupyter notebook), but not in a standalone IDE, for example, I use Spyder in Anaconda.

Could you edit the title and description of the issue to reflect this? Right now, you refer to the "Python console" which I take to mean a Python session launched directly from the terminal (bash, Windows command prompt, etc.) by typing the command "python".

I'm not sure how Spyder works as we only use and reliably support code launched from jupyter notebook/jupyter lab session, or from the terminal as in the paragraph above. Do other plotly figures show in your IDE?

cyinbox commented 4 years ago

@cyinbox thanks for the feedback.

The figures can be rendered in a browser (Jupyter notebook), but not in a standalone IDE, for example, I use Spyder in Anaconda.

Could you edit the title and description of the issue to reflect this? Right now, you refer to the "Python console" which I take to mean a Python session launched directly from the terminal (bash, Windows command prompt, etc.) by typing the command "python".

I'm not sure how Spyder works as we only use and reliably support code launched from jupyter notebook/jupyter lab session, or from the terminal as in the paragraph above. Do other plotly figures show in your IDE?

Thanks! I just edited the title of the bug. Besides Jupyter, development can also use standalone IDE, for example, Anaconda/Spyder, PyCharm, etc. We need to output the figures from these IDEs, so the code in standalone can be developed and deployed as a service. The figures generated from standalone also allows being justified for high-quality/resolution for publishing purpose. Therefore, rending a figure from standalone IDE is important.

cyinbox commented 4 years ago

yes, The Spyder/Anaconda3 IDE can produce other regular figures, but not from the giotto-tda plottings.

ulupo commented 4 years ago

Thanks again @cyinbox. However, the issue as it stands is not sufficiently detailed for us to act on it quickly. Could you furnish a step-by-step explanation of how to reproduce your situation, adding it to the issue description as per the issue template? I, for instance, use PyCharm so could quickly test there.

ulupo commented 4 years ago

The Spyder/Anaconda3 IDE can produce other regular figures

Could you also report on how to reproduce the examples which do work for you? Bear in mind they should be plotly figures to have a meaningful comparison.

cyinbox commented 4 years ago

The Spyder/Anaconda3 IDE can produce other regular figures

Could you also report on how to reproduce the examples which do work for you? Bear in mind they should be plotly figures to have a meaningful comparison.

Sure, thanks! I will describe it in detail. It probably just needs small code changes (figure shows).

wreise commented 4 years ago

I have managed to plot in the Spyder IDE, using a temporary workaround. I did the following:

  1. Install psutil and plotly-orca
  2. Change the plotly renderer to .svg (is it what one uses for publications?):
    import plotly.io as pio
    pio.renderers.default='svg'

    Maybe this allows you to temporarily visualize the solution.

cyinbox commented 4 years ago

I have managed to plot in the Spyder IDE, using a temporary workaround. I did the following:

  1. Install psutil and plotly-orca
  2. Change the plotly renderer to .svg (is it what one uses for publications?):
import plotly.io as pio
pio.renderers.default='svg'

Maybe this allows you to temporarily visualize the solution.

Thank you! Yes, that approach works. Or I can export the HTML rendered from plotly in giotto. plotly is for web-based interactive figures. Probably static figures plotting in giotto are also needed as new features.

wreise commented 4 years ago

@ulupo , do we have a plan on how to address this? Should we close?

ulupo commented 4 years ago

@wreise, I'm not sure. Let's discuss here.

I am curious about the last two statements by @cyinbox:

plotly is for web-based interactive figures.

This is not what I thought – plotly has plenty of support for high-quality offline plots. It is true that it is made to have particularly good support for web integration but also, importantly, for ipython (inc., but not only, Jupyter notebooks). The latter is an important strength for giotto-tda, as we encourage data exploration via interactive python sessions. Interactivity is essential for our interactive mapper graph solutions, for instance, and plotly is a great framework to use then.

Probably static figures plotting in giotto are also needed as new features.

We just found a way to produce them in vector format, and plotly HTML output can be saved as PNG with a simple click, so we would need more compelling reasons to move forward with integrating another plotting library. This has just been done e.g. in UMAP v0.4, and I just had a private conversation with the author who strongly advised against going in that direction unless it is vital (it was for his project).

There is another thing I'd like to share with @cyinbox: perhaps you are wondering why the transform_plot and fit_transform_plot methods do not return a plotly figure object, and instead go ahead calling fig.show() for the user. After all, if the figure were returned, the user could decide exactly what to do with it. The reason is that we want them to actually return data (ndarrays resulting from transform), while also showing a plot of the returned values. We also wanted to avoid returning a tuple (fig, output) as we thought it would make the workflow more clumsy.

For consistency, we also had the plot methods and the plotting functions in gtda.plotting show the figures and not return the figure objects. But perhaps we should revise that, and a little less consistency is a good price to pay for giving user access to the plotly.Figure objects and deciding how to show them, changing some of their attributes, etc.

@cyinbox, we could make a PR with minimal changes along the lines of the paragraph above. What do you think? Would you like me to go ahead and you could test the changes, or would you prefer to open a PR yourself?

cyinbox commented 4 years ago

Sorry for being late in replaying

I think the better approach is to add new functions in plotting tda diagrams using matplotlib, while keeping the plotly. The plot functions by matplotlib are for static figures, and the existing plotting functions by plotly are for interactive web figures.

@wreise, I'm not sure. Let's discuss here.

I am curious about the last two statements by @cyinbox:

plotly is for web-based interactive figures.

This is not what I thought – plotly has plenty of support for high-quality offline plots. It is true that it is made to have particularly good support for web integration but also, importantly, for ipython (inc., but not only, Jupyter notebooks). The latter is an important strength for giotto-tda, as we encourage data exploration via interactive python sessions. Interactivity is essential for our interactive mapper graph solutions, for instance, and plotly is a great framework to use then.

Probably static figures plotting in giotto are also needed as new features.

We just found a way to produce them in vector format, and plotly HTML output can be saved as PNG with a simple click, so we would need more compelling reasons to move forward with integrating another plotting library. This has just been done e.g. in UMAP v0.4, and I just had a private conversation with the author who strongly advised against going in that direction unless it is vital (it was for his project).

There is another thing I'd like to share with @cyinbox: perhaps you are wondering why the transform_plot and fit_transform_plot methods do not return a plotly figure object, and instead go ahead calling fig.show() for the user. After all, if the figure were returned, the user could decide exactly what to do with it. The reason is that we want them to actually return data (ndarrays resulting from transform), while also showing a plot of the returned values. We also wanted to avoid returning a tuple (fig, output) as we thought it would make the workflow more clumsy.

For consistency, we also had the plot methods and the plotting functions in gtda.plotting show the figures and not return the figure objects. But perhaps we should revise that, and a little less consistency is a good price to pay for giving user access to the plotly.Figure objects and deciding how to show them, changing some of their attributes, etc.

@cyinbox, we could make a PR with minimal changes along the lines of the paragraph above. What do you think? Would you like me to go ahead and you could test the changes, or would you prefer to open a PR yourself?

https://github.com/giotto-ai/giotto-tda/issues/387#issuecomment-611986141

ulupo commented 4 years ago

For consistency, we also had the plot methods and the plotting functions in gtda.plotting show the figures and not return the figure objects. But perhaps we should revise that, and a little less consistency is a good price to pay for giving user access to the plotly.Figure objects and deciding how to show them, changing some of their attributes, etc.

This has now been implemented in #441 and with the addition of plotly_params one has further control over how the figure is generated. Furthermore, since the figure is returned the user can export it in a convenient high-quality format (SVG, PDF, etc) if they so desire.

Unfortunately, we do not have the resources to satisfy @cyinbox's wish of having alternative matplotlib-based plotting functions at the moment, though I understand the sentiment. I suggest users dissatisfied with the former plotly approach try out the greater control given by the changes in #441, in case it is enough for their purposes.

I am closing this issue.