Jupyter + Observable

Hi all,

I’ve read Thomas series on Observable for Jupyter Users, thanks btw!, and was inspired to try this.

A Jupyter notebook with a reactive Observable visualization. I’m not sure if this is a common use case, but it might be useful sometimes.

Here is the Jupyter notebook source code on google collab and the observable notebook used as vizualization

Just curious if you know a better way to do that? without building custom widgets :stuck_out_tongue:

I’m using json.dumps() to serialize the data into the embed string.

def make_viz_embed(data, colors = [], labels = []):
  embed = f"""
    <div id="observablehq-0842ed87"></div>
    <script type="module">
    import {{Runtime, Inspector }} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
    import define from "https://api.observablehq.com/d/8bcaee9a68db388d.js?v=3";
    const inspect = Inspector.into("#observablehq-0842ed87");
    const notebook = (new Runtime).module(define, name => (name === "containerEl") && inspect());
    notebook.redefine('points', {json.dumps(data)})
    notebook.redefine('colors', {json.dumps(colors)})
    notebook.redefine('labels', {json.dumps(labels)})
    </script>
  """
  return embed

I couldn’t find a way to update the HTML widget in a more interactive way without re-running Jupyter cells after parameters changes.

Thanks

2 Likes

Theoretically you could rerun just the notebook.redefine lines, which you could enable by saying window.notebook = notebook. Not sure how to do it on the Jupyter side though.

This approach looks pretty good to me! Do you think Jupyter users would want something that pipes data in live vs requiring re-evaluating the cell to get new data in?

My initial thought (while I’ve been bundling up something like what you’ve got here) was that communicating directly with the Jupyter kernel would be more surprising. Since (as many Jupyter + Observable users are deeply aware) Jupyter doesn’t update cells automatically, tacking it on in this case feels weird to me, and I’d rather that getting new data in required reevaluating the cell.

What you’re describing is possible though! I’m just not sure what the user experience would be like. Similar to autocompletion calls to the kernel, it’s possible to make out-of-band calls to the kernel to evaluate an expression. I think your current solution is more or less the way to go, but curious about the use case you’re thinking of.

Hi Thomas,

You’re right about no need to pipe live data as Jupyter aways re-evaluates the cells. My concern was only on how to re-utilize the HTML embed context. For instance, in my example, the Observable embed uses a scatter plot lib with a WebGL context. I’m not sure if regenerating it after every Jupyter re-evaluation is a good practice? Maybe it’s not a problem as it’s an iframe and the browser would take care of it?

After all, the possibility of crafting custom visualizations in Observable and quickly integrate it on Jupyter notebooks seems very appealing . Especially for someone who enjoys the front-end/javascript side of data analysis and the powerful capability of Jupyter kernels.

Thanks for spending time on it.

1 Like