jupyterlab version of python

149 views
Skip to first unread message

Steve Spicklemire

unread,
May 22, 2018, 9:11:57 AM5/22/18
to Project Jupyter
Hi Jupyter folks,

I'm hoping to carve out some time in the next few weeks to make some serious progress on a jupyterlab compatible version of vpython (http://vpython.org).

The jupyter notebook interaction of vpython involves opening a communication channel (ipykernel.comm.Comm) between the kernel process and a javascript program running in the browser handling the display. The javascript code is currently embedded in the python package (site-packages/vpython/vpython_libraries/) and transferred into nbextensions on demand and then pulled into the notebook using ipython.display.display.

It has been suggested that this whole scheme needs to be redesigned under jupyterlab. I'm hoping to begin that design process now, but being new to jupyterlab, I'm not really sure where to begin. I did read through the tutorials for jupyterlab extensions, but I'm not clear what sort of extension would be needed here since it doesn't seem to exactly match the use cases described in the exam extensions. I'd love some input from any jupyterlab veterans about how we should go about planning/building this. Ideally users would be able to take code that works in the jupyter notebook, and run it unchanged in jupyterlab.

something like:

-------
from vpython import *

s=sphere()

--------

without needing any magics or other python code if possible.

thanks,
-steve

Steve Spicklemire

unread,
May 22, 2018, 9:13:16 AM5/22/18
to Project Jupyter
Ack! Of course my browser cleverly turned "vpython" into "python" and I didn't catch it!

sorry.
-steve

John

unread,
May 22, 2018, 10:02:35 AM5/22/18
to Project Jupyter
For classic jupyter notebook, vpython is copying javascript files to the nbextensions directory by calling the routine

notebook.nbextensions.install_nbextension()

from the vpython package directory. (site-packages/vpython/vpython_libraries/) . These javascript files are loaded into the notebook from the nbextensions directory using ipython display method along with requirejs.

display(Javascript("""require(["nbextensions/vpython_libraries/glowcomm"], function(){console.log("GLOWCOMM LOADED");})"""))
This works in classic jupyter notebook but not in Jupyterlab . Does jupyterlab use the nbextensions directory or does it is place javascript fles in a different directory. What should be used in place of requirejs to load javascript files?

Steve Spicklemire

unread,
May 22, 2018, 10:10:38 AM5/22/18
to jup...@googlegroups.com, Steve Spicklemire
My understanding is that webpack is used, but that’s based on the tutorials I read. Have I got that right?

thanks,
-steve
> --
> You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
> To post to this group, send email to jup...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/279ebceb-50f6-49fb-aae2-f3e74cf04009%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Jason Grout

unread,
May 22, 2018, 11:45:36 AM5/22/18
to jup...@googlegroups.com, Steve Spicklemire
Right, JLab uses it's own extension system, and webpack to bundle javascript up, and does not use require or the nbextension system.

I think maybe you can do something like this for the first steps:

1. Write an npm package containing the vpython javascript. JLab extensions are fundamentally npm packages containing some extra metadata.
2. Write a very simple extension (perhaps like the beginning steps of the xkcd extension?) whose sole purpose is to get the js on the page. You do this by importing the vpython js modules into your main extension file that JupyterLab loads.
3. Decide how vpython is going to display. It seems that there are lots of parallels with ipywidgets and vpython, so you might look to ipywidgets for inspiration. For example, we now display using the ipython display system and a custom widget mimetype and custom mimetype renderer.

Jason


Matt Craig

unread,
May 22, 2018, 10:02:59 PM5/22/18
to Project Jupyter
I'm a little biased, but like the idea of moving towards an ipywidgets-based interaction with the notebook (i.e. vpython as a widget)....can probably help with that later this summer once SciPy is done :)

Matt

Steve Spicklemire

unread,
Jun 4, 2018, 6:36:23 AM6/4/18
to jup...@googlegroups.com, Steve Spicklemire
Hi JupyterLab folks,

As usual I have more questions than answers!

So I’m thinking this sounds like more or less the kinds of interaction that would work:

http://jupyterlab.readthedocs.io/en/stable/developer/notebook.html#the-ipywidgets-third-party-extension

This note at the end:

"Note: The ipywidgets third party extension has not yet been released.”

Is that (still) true? Does it simply mean that, like much of the ecosystem, it’s still in it’s testing phase?

Could anyone recommend an exemplary ipywidget implementation one might refer to as a starting point?

Finally, the current system (vpython7/glowscript) is built around ES5, and AMD (requirejs). I’m seeing that jupyterlab appears to prefer commonjs and typescript. Is it possible to mingle these? If not, is there any guidance offered for migrating a codebase from ES5/AMD to typescript/react/commonjs?
>> To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/af3e0de0-a1c2-4edc-bc1a-9eb601cb60e0%40googlegroups.com.

John

unread,
Jun 6, 2018, 8:14:16 AM6/6/18
to Project Jupyter
Hi Steve

   I managed to get a simple Comm channel example from classic jupyter notebook for opening a comm from the kernel


to work using jupyterlab machinery. It uses DocumentRegistry.IWidgetExtension  in the front end and the sample code to set up the Comm from the for the above example looks like the following in index.ts file.


declare var require: any

import {
  IDisposable, DisposableDelegate
} from '@phosphor/disposable';

import {
  JupyterLab, JupyterLabPlugin
} from '@jupyterlab/application';

import {
  DocumentRegistry
} from '@jupyterlab/docregistry';

import {
  NotebookPanel, INotebookModel
} from '@jupyterlab/notebook';

import { myFunction } from './myModule'

/**
 * The plugin registration information.
 */
const plugin: JupyterLabPlugin<void> = {
  activate,
  id: 'jupyterlab_expext',
  autoStart: true
};


/**
 * A notebook widget extension to try things out.
 */
export
class ExperimentalExtension implements DocumentRegistry.IWidgetExtension<NotebookPanel, INotebookModel> {
  /**
   * Create a new extension object.
   */
  createNew(panel: NotebookPanel, context: DocumentRegistry.IContext<INotebookModel>): IDisposable {
    Promise.all([panel.ready, panel.session.ready, context.ready]).then(function() {
const session = context.session;
const kernelInstance = session.kernel;
//const notebook = panel.notebook;
kernelInstance.registerCommTarget('my_comm_target', (comm) => {
comm.onMsg = handler
//comm.onMsg = (msg) => {console.log("onMsg : "+msg.content.data);comm.send(msg.content.data);};
comm.onClose = (msg) => {console.log("onClose");};
comm.send({'foo': 0});
});
    });
    return new DisposableDelegate(() => {});
  }
}

/**
 * Activate the extension.
 */
function activate(app: JupyterLab) {
  app.docRegistry.addWidgetExtension('Notebook', new ExperimentalExtension());
  console.log('Test JupyterLab extension jupyterlab_expext is activated!');
};


function handler (msg: any) {
console.log("handler onMsg : " + msg.content.data);
if (msg.content.data['foo'] == 10) {
console.log("foo == 10");
myFunction();
}
};


/**
 * Export the plugin as default.
 */
export default plugin;



The contents of myModule.ts are

export function myFunction() {
    document.getElementById("demo").innerHTML = "Paragraph changed.";
}

I put the kernel code from the example for setting up a comm channel in a jupyterlab notebook cell and tested that I get bidirectional communication.

from ipykernel.comm import Comm
# Use comm to send a message from the kernel
my_comm = Comm(target_name='my_comm_target', data={'foo': 1})
my_comm.send({'foo': 2})

msg2 = None

# Add a callback for received messages.
@my_comm.on_msg
def _recv(msg):
    global msg2
    # Use msg['content']['data'] for the data in the message
    msg2 = msg['content']['data']


I also tested that HTML code in notebook cell output area is modified when above myFunction is called.

from IPython.core.display import HTML

HTML("""
<head>

</head>

<body>

<h2>JavaScript in Head</h2>

<p id="demo">A Paragraph.</p>

</body>

""")

 
The contents of element with id "demo" get changed to "Paragraph changed" when you execute this code in a notebook cell.

my_comm.send({'foo': 10})

The above example demonstrates basic functionality of setting up a Comm channel in jupyterlab and manipulating HTML in output cell in notebook from typescript code in jupyterlab extension.


John

John

unread,
Jun 6, 2018, 9:06:54 AM6/6/18
to Project Jupyter
I found this tutorial useful for learning about how to implement JupyterLab extensions.


Based on this example I modified it and instead of displaying an image I displayed an html canvas element. First I tried a canvas element with a 2d context to display 2d content . I also tried a canvas element with a webgl context and was able to display webgl content in jupyterlab window using the above tutorial as a starting point.

You might also find the webpack tutorial helpful.


Also look at webpack shimming imports-loader for loading legacy third party javascript code.



John

John
Reply all
Reply to author
Forward
0 new messages