cytoscape / ipycytoscape

A Cytoscape Jupyter widget
https://ipycytoscape.readthedocs.io/en/master/
BSD 3-Clause "New" or "Revised" License
269 stars 62 forks source link

Support for Notebook HTML Export #80

Open Phocion opened 4 years ago

Phocion commented 4 years ago

Really appreciate this project for bringing much-needed graph interactivity to Jupyter.

Was wondering if there are plans to have the graph exported properly into HTML notebook exports? Something akin to Plotly's plotly.offline.iplot(...) function. I recall needing one additional step to get interactive Plotly plots to export correctly in Jupyter Notebook HTML exports: https://blog.matteoferla.com/2019/06/exporting-jupyter-notebooks-with-plotly.html

The target audience who would make good use of these graphs in HTML reports don't use Jupyter Notebooks and wouldn't use it as a medium to explore them. So it would be a vital feature to make available such that the exports show the analysis results for interpretation.

(And I'm not including ipywidgets interactivity here - just the graph itself as it would appear embedded in a normal HTML webpage.)

Is this doable?

Many thanks!

marimeireles commented 4 years ago

Hi @Phocion! I think it's even possible to make it interactive, at least, that's what voila is doing, do you know it? I just tested it with ipycytoscape and it seems to work fine, but I didn't try anything complicated here. (Soon we'll also have a tool to convert html and notebooks to pdfs and slideshows :D)

If you're using it and manage to create some cool visualizations and interactions between native widgets and ipycytoscape with your use case I'd be very interested in having it in the https://voila-gallery.org/!

Don't hesitate to ping me for a quick chat or in github if you run to any issues.

ianhi commented 4 years ago

I think Voila runs a python kernel underneath to enabled continued interaction with python? So its not quite the same as exporting to standalone HTML. Correct me if I'm wrong but I think @Phocion is talking about File > Export Notebook As > Export as HTML. But that doesn't save with a working widget. The steps to get that to work are:

  1. Ensure that widget state gets saved: image
  2. Use the nbconvert CLI: jupyter nbconvert --to html <your file>.ipynb

You need to use the CLI due to a difference in the nbconvert cli and python api detailed here: https://github.com/jupyterlab/jupyterlab/issues/7262

I followed the above to embed the cola example into an standalone html file in this zip: Cola example.zip is that what you were looking for?

I wonder how hard it would be to have a method on the widget like export_to_html that would create a standalone interactive graph without the rest of the jupyter notebook like the above steps produce. I think this would basically be doing whatever nbconvert does, but stripping away everything that isn't the cytoscape widget.

ianhi commented 4 years ago

A minimal embedding is not so hard it turns out, most of the NBconvert output can be removed without consequence (there's like 10000 lines of css). The widget state gets saved in a script tag and then all you need is the html below. It's probably also possible to get that widget state from within python, but idk how.

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" />

<title>Cola example</title>

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>

<script>
(function() {
  function addWidgetsRenderer() {
    var mimeElement = document.querySelector('script[type="application/vnd.jupyter.widget-view+json"]');
    var scriptElement = document.createElement('script');
    var widgetRendererSrc = 'https://unpkg.com/@jupyter-widgets/html-manager@*/dist/embed-amd.js';
    var widgetState;

    // Fallback for older version:
    try {
      widgetState = mimeElement && JSON.parse(mimeElement.innerHTML);

      if (widgetState && (widgetState.version_major < 2 || !widgetState.version_major)) {
        widgetRendererSrc = 'https://unpkg.com/jupyter-js-widgets@*/dist/embed.js';
      }
    } catch(e) {}

    scriptElement.src = widgetRendererSrc;
    document.body.appendChild(scriptElement);
  }

  document.addEventListener('DOMContentLoaded', addWidgetsRenderer);
}());
</script>
</head>

<body>

<script type="application/vnd.jupyter.widget-view+json">
{"model_id": "ab5aaa0452754cf9ae1d3905a743e3dc", "version_major": 2, "version_minor": 0}
</script>

</body>

<script type="application/vnd.jupyter.widget-state+json">
{"state": {"005090b598af4b7580b05745803d2862": {"model_module":
....
....
....
rohanvarm commented 3 years ago

Has there been an update to this? Is it still open?

marimeireles commented 3 years ago

Hi @rohanvarm, could you please tell me about your use case? Voila isn't enough for it? Have you tried nbconvert?