pyviz / pyviz.org

Source for the PyViz.org website.
https://pyviz.org
Other
151 stars 50 forks source link

Minimal shared library spec #32

Open jsignell opened 5 years ago

jsignell commented 5 years ago

There was discussion at SciPy sprints about having a shared API for accessing objects from various plotting libraries. We think there could be a spec for common actions such as save, show, html_repr. This issue is to start that discussion. @munkm @tacaswell @jonmmease

jonmmease commented 5 years ago

Thanks @jsignell, here are some API entry points in plotly.py (as of version 4, which is in release candidate stage at the moment) that might be candidates for inclusion in a spec (and definitely open to renaming if the concepts make sense but other names are preferred). I've numbered the ideas to aid discussion.

.show() method

1) The top-level figure class has a .show() method that can be called without arguments to display the figure as a side-effect. 2) The optional renderer kwarg can be used to override the current default renderer. e.g.:

Self-displaying figures

3) When figures are displayed in an ipython context, we use the _ipython_display_ protocol to call fig.show().

Exporting figures

Figures have write_* and to_* methods for exporting/converting figures. We don't currently have a .save method because it would be a bit ambiguous in our case.

4) The write_* methods write the figure to a file (or writable object) and return None. If the first argument to a write_* method is a string, then it is treated as a local file path that can be opened with the standard Python open function. Otherwise, the object passed as the first argument is assumed to be writable (i.e. to have a .write method). Beyond the first required argument, each export approach can have its own optional configuration kwargs. For example

Or with a writable object

with open('/path/to/output.html', 'w') as f:
    fig.write_html(f, include_plotlyjs='cdn')

5) The to_* methods return an in-memory representation of the exported figure and don't write any files. They should have the same signature as the corresponding .write method without the first file argument. Ideally, these methods can be called with no arguments and reasonable defaults are chosen. For example:

Accessing root figure

6) Every object in the figure hierarchy (plotly.py calls these "graph objects") has a .figure property that returns the parent figure, if any, or None if the graph object does not belong to a figure.

jbednar commented 5 years ago

That sounds really cool! I'd go further and say that such a spec should get a name and revision and have an associated repo in the pyviz organization, with automated tests that define whether each library meets the spec up to revision X (which can be shown in a status page like pyviz.org/tools.html). Seems like a great way to use the pyviz organization!

jbednar commented 5 years ago

I'd also propose that the spec include support for the various IPython rich display methods, i.e. repr_html, repr_png, etc. so that each library could be treated the same in how things are displayed inline.

djhoese commented 5 years ago

Very interesting idea. Always a big fan of consistency. I have some questions though: Would this spec only apply to plotting interfaces of a library that provide a specific "figure" object? Do most plotting or visualization libraries provide that? What about generic visualizations or animation that may or may not be a "plot" (axes, ticks, etc)?

If a library has every method, but doesn't have a JSON representation for its figures (so no to_json) does it now look "less complete" on the PyViz site because it can't implement every piece of the spec?

jbednar commented 5 years ago

I would say that if a given operation doesn't make sense for that library, then it could satisfy the spec by simply having that method return a message to that effect ("JSON support not available in x-viz").

I don't think any of the operations involved here would require axes, ticks, etc., just a viewable representation.

I'm not sure about the semantics required of "figure"; to me that would just be "some object that has a visible representation but which can also be saved, exported, etc.".

jakevdp commented 5 years ago

This is a great idea. I'm happy to implement in Altair as soon as there's consensus on the spec.

jakevdp commented 5 years ago

Another thing that might be useful: a uniform way to enable various libraries in jupyter notebook & jupyterlab. For example, matplotlib has %matplotlib inline, bokeh has bokeh.output_notebook(), altair has alt.renderers.enable('notebook'), etc. If every library agreed to define something like %enable_{LIBNAME}, things would be much more predictable for the user.

jbednar commented 5 years ago

A uniform way to enable various libraries in jupyter is a great idea, but I would argue that such a specification should not rely on magics. We routinely use Jupyter notebooks as literate programming environments for developing and sharing code that we need to be usable both within and outside of jupyter; e.g. with many of our notebooks we can do panel serve nb.ipynb to launch them as standalone dashboards without Jupyter involved at all. We can always add special cases to deal with magics, but I don't think that's a good idea; I greatly prefer just to have a normal Python call that can register things with Jupyter if it's available but doesn't otherwise cause syntax errors (if not skipped) or missing functionality (if skipped) outside of Jupyter/IPython.

jakevdp commented 5 years ago

Sure, makes sense.

jsignell commented 5 years ago

I wrote up these initial ideas at https://github.com/pyviz/spec/tree/01_02_03 and made you all admin of that repo. Please comment over there. Ping me if you want to be part of that discussion and haven't been added.