python-igraph icon indicating copy to clipboard operation
python-igraph copied to clipboard

Ease of use in various environments

Open szhorvat opened this issue 4 years ago • 15 comments

Accessibility and ease of use is an important goal for igraph. I would love to see it being easy to use in various popular interactive environments. I reached out to https://cocalc.com to ask that python-igraph be a default package. They were supportive and it will be included in the next release. Plotting works fine.

Another very popular such environment is Google Colab https://colab.research.google.com/ I cannot get plotting working there, even after successfully installing pycairo.

We should look into which environments people might use python-igraph, and either work with the developer of that environment to make it work, or provide instructions on how to make igraph work.

@iosonofabio Is this something you'd be interested in looking into, in particular getting plotting working in Google Colab?

szhorvat avatar May 20 '21 14:05 szhorvat

For the record, this is what I tried:

!apt install libcairo-dev
!pip install pycairo
!pip install python-igraph
import igraph as ig
g=ig.Graph.Erdos_Renyi(n=100,m=200)
ig.plot(g)

It gives me a very unhelpful AttributeError: plotting not available, with no hints on where to look for solutions. I would consider this a user experience bug.

szhorvat avatar May 20 '21 14:05 szhorvat

The AttributeError: plotting not available error appears when import cairo fails with an ImportError; we catch the exception and replace cairo with a fake module that raises an AttributeError for every single attribute access. Note that from inside Python, it is hard to distinguish between a missing pycairo library and a pycairo library that fails to import for other reasons.

For sake of completeness, I should mention that we also try cairocffi, an alternative Cairo frontend that is API-compatible with cairo itself.

I tried to reproduce the issue, but the snippet that you sent works just fine for me; here is a Colab notebook where I successfully managed to plot a graph:

https://colab.research.google.com/drive/1Lkywky1AKEmDcW235nD4EvopTt_gCcZi?usp=sharing

ntamas avatar May 20 '21 19:05 ntamas

Anyway, we can try improving the plotting not available error message, but there's only so much we can put into an exception message (some environments might truncate the string). We can try something like `Plotting not available. Try running "pip install cairocffi" or "pip install cairo" if you haven't done so yet.", but as you can see, this message would not have been very helpful in your case.

Another option is to put a permalink in the message that leads the user to the appropriate chapter in the Python tutorial, where we can add more detailed instructions.

ntamas avatar May 20 '21 19:05 ntamas

You are right, it works in Google Colab. I did not realize that closing and re-opening the notebook in Colab does not necessarily restart the kernel. That's why it failed.

szhorvat avatar May 20 '21 20:05 szhorvat

Part of the reason behind the matplotlib PR was that mpl works in all these situations: the notebook/colab folks make sure of that, so that makes our life easier.

I'm unsure how you guys feel about it, but I would conceive switching entirely to mpl as default within the next year or so

iosonofabio avatar May 20 '21 21:05 iosonofabio

There is a lot of value in going with the standard. It helps interoperability. If it reaches feature parity with the Cairo backend, and there is no major performance downside (I never measured!), it sounds like a good idea to make it the default.

It would be also nice to add some examples / tutorial pages that show off what you can do with the matplotlib backend that you couldn't easily do with Cairo, such as combining with other plots and other graphics elements.

So far the one important lacking feature I noticed is support for multi edges, #395

szhorvat avatar May 21 '21 09:05 szhorvat

#395 is closed now, and I just added some info to the visualization docs about at least two common situations where matplotlib is useful. Shall we close this issue then?

iosonofabio avatar Jun 29 '21 08:06 iosonofabio

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 28 '21 11:08 stale[bot]

The plotting PR brings mpl and plotly to parity with Cairo. I expect that to take help with colab, data bricks, notebook, jupyterlab, etc.

iosonofabio avatar Aug 28 '21 23:08 iosonofabio

For the record, I tried this again on Google Colab with the following script:

!pip install python-igraph
import igraph as ig
g = ig.Graph.Erdos_Renyi(n=100, m=200)
ig.plot(g)

It still complains about Cairo as that one is the default plotting backend. matplotlib is installed in Google Colab by default, so I was wondering whether we should try to be smart and select a plotting backend based on what's available (while still preferring Cairo for the time being if the user has both, for sake of backwards compatibility). This would make igraph much easier to use in notebook environments with matplotlib; right now the user would need to realize that there are actually multiple plotting backends and that the backend can be switched to matplotlib.

ntamas avatar Oct 14 '22 16:10 ntamas

What about:

If you don't have Cairo but you have matplotlib and your config is set to Cairo, we print a warning message immediately telling the user how to set mpl as backend?

iosonofabio avatar Oct 14 '22 19:10 iosonofabio

I was wondering how we could test for the presence of matplotlib without importing it. I'm a bit worried that importing matplotlib directly has side effects like the initialization of Matplotlib's plotting backends, which might take too much time and might do stuff that we don't want (e.g., starting an X server on macOS?).

ntamas avatar Oct 17 '22 08:10 ntamas

Loading matplotlib also breaks checking for leaks with LeakSanitizer.

szhorvat avatar Oct 17 '22 08:10 szhorvat

Maybe this?

import importlib
spec = importlib.util.find_spec("matplotlib")
found = spec is not None

ntamas avatar Oct 17 '22 08:10 ntamas

yes:

https://stackoverflow.com/questions/14050281/how-to-check-if-a-python-module-exists-without-importing-it

iosonofabio avatar Oct 17 '22 09:10 iosonofabio