gijzelaerr / js9notebook

embed JS9, the browser based DS9, into a Jupyter notebook
Other
1 stars 1 forks source link

integrating js9 into jupyter #2

Closed ericmandel closed 6 years ago

ericmandel commented 8 years ago

Hi Gijs,

When you are ready to work on integrating/packaging, please see:

http://python.6.x6.nabble.com/embedding-js9-into-a-notebook-tp5173096p5178697.html

where Nicholas Bollweg says:

Let me know when you are thinking you've advanced to the point where you want to try to package the whole thing in a repo. It would be easier to start collaborating on code, and then be able to get a binder (mybinder.org) going, then consider how to proceed: pure js nbextension, python backend (widgets), etc.

ericmandel commented 8 years ago

The following now also works in a jupyter notebook:

%%html
<iframe src="http://js9.si.edu" width=1000 height=750></iframe>

Cross-site framing was blocked on the js9 web site, but it works now.

So another option we have is to create a number of static Web pages that users can utilize, e.g.:

  1. js9 + menubar
  2. js9 +menubar + panner + magnifier
  3. two js9 instances
  4. .... etc ....

Not sure how I feel about this, but the iframe does immediately give you full access to JS9 functionality. A lot depends on how you think users will want to interact with JS9.

o-smirnov commented 6 years ago

I'd like to pick this up again: https://github.com/ratt-ru/radiopadre-devel/issues/2

o-smirnov commented 6 years ago

@ericmandel, would you mind if we added you to that repository? I think we could use really your help on the JS9 side.

ericmandel commented 6 years ago

Yes, of course. Are you aware of this effort? https://github.com/mgckind/jjs9, with some relatively status discussed here: https://github.com/ericmandel/js9/issues/30

I think Matias is still interested, so maybe you all should talk as well? (My knowledge of Jupyter is essentially null, though I'm very interested in have a JS9/Jupyter connection working well.)

cc: @mgckind @DougBurke

o-smirnov commented 6 years ago

My knowledge of Jupyter is essentially null

Which nicely complements my knowledge of Javascript and web programming in general. :) Fortunately there's bright young people like @gijzelaerr and @Mulan-94 to figure it out for us.

The scenario I'd like to use it in is as follows. We're developing Jupyter notebooks to visualize the results of data processing pipelines. This often means looking at a lot of FITS images sitting on a remote machine, with network lag making X11 forwarding not very practical. JS9 looks like the answer.

I think this fits the last scenario described by @mgckind on https://github.com/mgckind/jjs9, so we're going to give that a try first. I have to say I'm a little confused what a "JS9 server" actually does. I assume in the last scenario ("users who run Jupyter notebook remotely on a server") I still need to run js9_web.py and js9Helper.js on that same server?

Ideally, I'd like this thing to be "installation-free", i.e. requiring nothing more than ssh access to the remote server. For our notebooks this is already pretty smooth and automatic (ssh in, create a virtualenv, pip install Jupyter into it, run it, and forward its port over ssh), so maybe I need to ask @gijzelaerr and @Athanaseus to package JS9 and https://github.com/mgckind/jjs9 into KERN and/or PyPI.

ericmandel commented 6 years ago

I have to say I'm a little confused what a "JS9 server" actually does.

In this context, the JS9 helper is facilitating the communication between Python (or the shell) and JS9, since its not possible for an external program to communicate directly with a browser. JS9 inside the browser connects to the server-side helper (when available) when the web page loads. The pyjs9.JS9() routine connects to the same helper so that it can send JS9 requests when you call an API routine. Subsequently, the helper relays API requests to the connected browser and returns the results to Python.

Additionally, the LoadProxy() API call referenced in @mgckind's example requires a JS9 helper so that the server can retrieve the remote FITS file and then tells JS9 its location so that JS9 can make a request to load it.

The JS9 helper also supports server-side analysis and some other things ...

o-smirnov commented 6 years ago

OK, so the helper is run server-side with node js9Helper.js, correct? And how exactly does the JS9 on my local browser talk to the remote JS9 helper? Do I need to specify ports/etc.?

When I naively try to JS9.LoadProxy() on the client, I get a popup saying JS9 ERROR: no JS9 helper available. If I try JS9.Load(), I get JS9 ERROR: no FITS module available to process FITS file. If I try @mgckind's last example, I also get the "no FITS module" error.

I did configure, build and install JS9 with cfitsio support, and I'm running node js9Helper.js on the server. I see this has a port set up (2718) -- does this need to be known on the browser side somehow?

o-smirnov commented 6 years ago

I'm seeing this in the JS console when setting up a JS9 display. Don't know if this is related:

VM404:240 Uncaught ReferenceError: io is not defined
    at Object.success (eval at globalEval (jquery.min.js:2), <anonymous>:240:67)
    at i (eval at globalEval (jquery.min.js:2), <anonymous>:18:28017)
    at Object.fireWith [as resolveWith] (eval at globalEval (jquery.min.js:2), <anonymous>:18:28783)
    at A (eval at globalEval (jquery.min.js:2), <anonymous>:20:14035)
    at HTMLScriptElement.c (eval at globalEval (jquery.min.js:2), <anonymous>:20:17354)
    at HTMLScriptElement.dispatch (eval at globalEval (jquery.min.js:2), <anonymous>:19:10316)
    at HTMLScriptElement.q.handle (eval at globalEval (jquery.min.js:2), <anonymous>:19:8343)
ericmandel commented 6 years ago

OK, so the helper is run server-side with node js9Helper.js, correct? And how exactly does the JS9 on my local browser talk to the remote JS9 helper? Do I need to specify ports/etc.?

When you build JS9, you have the option to specify what sort of helper (CGI also supported but not recommended), including no helper at all. You also can specify the helper port. Configuration params are stored in js9prefs.js and js9Prefs.json. The latter's use of synchronous load is unfortunately deprecated by FF, so its use cannot recommended in the client. But it is loaded by the JS9 helper, so the two files should be consistent, at least for now (I know I have to deal with this at some point). If you look at them you should see something like this:

 "globalOpts": {"helperType":  "nodejs", "helperPort":  2718, ...

This info is loaded into the helper at startup and sent to the browser when the page is loaded, so they both know the protocol and the port. Once the browser knows this info, it will try to connect to the helper. If you choose File -> display pageid and see "none", you can be sure the connect failed. But I think we know that from this message:

VM404:240 Uncaught ReferenceError: io is not defined

I am guessing that you did not start the node js9 helper in the js9 install directory (or in the cloned directory), i.e., where the node_modules directory is located. As a result, node could not find the socketio modules when trying to respond to the browser's request for connection.

Documentation is here, and if you have already read it, that means I did not explain it clearly:

https://js9.si.edu/js9/help/helper.html

mgckind commented 6 years ago

Thanks for mentioning me, I was very excited when it was working, then given the fast development on the Jupyter side it was hard to keep track of all changes and got busier in other things . We still do want this to work again, so I'll try to follow this conversation very closely.

o-smirnov commented 6 years ago

Thanks @ericmandel. Indeed "Display pageid" comes back with None, so I guess there's something wrong with the helper. I do start nose js9Helper.js in the install directory (i.e. what I configured via --with-webdir -- that is the one you mean? In any case I see node_modules/socket.io under it).

My js9Prefs.json looks like this.

{
  "globalOpts": {"helperType":       "nodejs",
         "helperPort":       2718, 
         "helperCGI":        "./cgi-bin/js9/js9Helper.cgi",
         "fits2png":         false,
         "debug":        0,
         "loadProxy":        true,
         "workDir":      "./tmp",
         "workDirQuota":     100,
         "dataPath":         "$HOME/Desktop:$HOME/data",
         "analysisPlugins":  "./analysis-plugins",
         "analysisWrappers": "./analysis-wrappers",
                 "installDir":       "/files/js9-www"
         },
  "imageOpts":  {"colormap":         "grey",
         "scale":            "linear"}
}

I'm a bit uncertain about the installDir setting. What I have it set to is the path that the Jupyter webserver serves it up as. Should it be the real filesystem path instead?

Also, is there any way to get the helper to print any sort of debug or status messages? I tried bumping the debug setting above, but it remains completely silent.

ericmandel commented 6 years ago

I'm a bit uncertain about the installDir setting

I don't think you want to mess with the installDir property right now. It's a back door for cases where JS9 can't figure out how to get from the web page to the installation directory (usually then the js9.css file is manually installed somewhere other than the js9 install directory) . I'd recommend removing for now.

any way to get the helper to print any sort of debug or status messages

You can turn on more node.js debugging than you thought possible this way:

DEBUG='*' node js9Helper.js 

A more nuanced view is described here (for example):

https://nodejs.org/api/debugger.html
o-smirnov commented 6 years ago

OK, but I still need the installDir set in js9prefs.js, because without it I get all sorts of 404s in the JS console.

So I did enable debug messages. What I get is

(.radiopadre-venv) oms@jakob:~/radiopadre/js9-www$ DEBUG='*' node js9Helper.js 
  socket.io:server initializing namespace / +0ms
  socket.io-parser encoding packet {"type":0,"nsp":"/"} +3ms
  socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +2ms
  socket.io:server creating engine.io instance with opts {"maxHttpBufferSize":10000000000,"path":"/socket.io","initialPacket":["0"]} +0ms
  socket.io:server attaching client serving req handler +7ms

on startup, followed by

  socket.io:server serve client source +9s

every time I redisplay the Jupyter cell that creates a JS9 display. So it's talking to the helper at least. But on the browser side I still have Uncaught ReferenceError: io is not defined (as well as Uncaught TypeError: Cannot read property 'mouse' of undefined), and display pageid is still None.

ericmandel commented 6 years ago

OK, I was totally confused and thought you were not inside Jupyter anymore, but were testing the usual use of a browser directly. Can you please try a direct browser page load and make sure the helper connects successfully in that case? If the browser does work as expedcted, then I really have to try to reproduce this problem here at CFA and debug it.

o-smirnov commented 6 years ago

OK, so if I load http://localhost:11003/files/js9-www/js9.html in a new browser tab, I get a JS9 window with a proper page ID (and all sorts of colorful debug output from the node helper).

So, indeed it seems that the problem only arises when displaying this under Jupyter.

o-smirnov commented 6 years ago

then I really have to try to reproduce this problem here at CFA and debug it.

I'm happy to dig further, but I'm flying blind at this point. Let me know if it would be useful for me tro try anything else.

o-smirnov commented 6 years ago

in a new browser tab, I get a JS9 window with a proper page ID

That said, there's still a few errors in the JS console. Perhaps unrelated:

Failed to load http://localhost:11003/files/js9-www/astroemw.wasm: Redirect from 'http://localhost:11003/files/js9-www/astroemw.wasm' to 'http://localhost:11003/login?next=%2Ffiles%2Fjs9-www%2Fastroemw.wasm' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
js9.min.js:413 Ignored call to 'alert()'. The document is sandboxed, and the 'allow-modals' keyword is not set.
b.error @ js9.min.js:413
g.onerror @ js9.min.js:402
XMLHttpRequest.send (async)
(anonymous) @ VM53:1
b.fetchURL @ js9.min.js:403
b.initEmscripten @ js9.min.js:472
b.init @ js9.min.js:564
(anonymous) @ js9.min.js:620
j @ js9support.min.js:18
k @ js9support.min.js:18
setTimeout (async)
(anonymous) @ js9support.min.js:18
i @ js9support.min.js:18
fireWith @ js9support.min.js:18
fire @ js9support.min.js:18
i @ js9support.min.js:18
fireWith @ js9support.min.js:18
ready @ js9support.min.js:18
S @ js9support.min.js:19
js9.min.js:413 Uncaught Error: cannot load: /files/js9-www/astroemw.wasm  .. please check the url/pathname
    at Object.b.error (js9.min.js:413)
    at XMLHttpRequest.g.onerror (js9.min.js:402)
ericmandel commented 6 years ago

js9.min.js:413 Uncaught Error: cannot load: /files/js9-www/astroemw.wasm .. please check the url/pathname

This is very bad, and is caused to your setting installDir. I think you should remove that line from your prefs, verify that this error goes away in the bowser, and let me try to reproduce the Jupyter problem.

o-smirnov commented 6 years ago

and is caused to your setting installDir.

I removed installDir, same problem. What about the first line, something about CORS policy?

o-smirnov commented 6 years ago

P.S. I should point out, Jupyter is still playing static webserver here (hence the /files prefix on the URL), so perhaps this is also contributing to the problem?

ericmandel commented 6 years ago

OK, perhaps I am wrong in my diagnosis, its hard to do this remotely ... so let's try turning off use of wasm by JS9, by setting this parameter in js9prefs.js:

globalOpts.useWasm: false

That will use asm.js instead.

ericmandel commented 6 years ago

Aside from turning off wasm, you can try avoiding Jupyter entirely by using the Python web server instead, something like:

python -m SimpleHTTPServer 8000
ericmandel commented 6 years ago

@o-smirnov @mgckind I have updated my version of Jupyter and now I get all of the error messages mentioned above:

screen shot 2018-07-03 at 1 04 16 pm

So, not sure how far I will get with the black-box that is Jupyter, but let me fiddle with JS9 for a while and see if I can get anything to work.

o-smirnov commented 6 years ago

Thanks, I feel comforted it wasn't just me screwing up in ignorance. :)

I've clocked out for today, but happy to continue hacking on this tomorrow, if I can help at all.

On Tue, 03 Jul 2018, 19:06 Eric Mandel, notifications@github.com wrote:

@o-smirnov https://github.com/o-smirnov @mgckind https://github.com/mgckind I have updated my version of Jupyter and now I get all of the error messages mentioned above:

[image: screen shot 2018-07-03 at 1 04 16 pm] https://user-images.githubusercontent.com/3028875/42234171-9ea4ec14-7ec1-11e8-9361-a3813031d283.png

So, not sure how far I will get with the black-box that is Jupyter, but let me fiddle with JS9 for a while and see if I can get anything to work.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/gijzelaerr/js9notebook/issues/2#issuecomment-402227698, or mute the thread https://github.com/notifications/unsubscribe-auth/AGK5v4OXWTNu0-SKI-tedcdTBKqCL2vLks5uC6SVgaJpZM4Gw5JX .

ericmandel commented 6 years ago

@o-smirnov @gijzelaerr @mgckind

OK, I've debugged JS9 under Jupyter as far as I can go:

tl;dnr: iframe works, direct load of js9-allinone.js almost works (but no js9 helper in the latter case)

After re-familiarizing myself with the whole issue, I realized that direct loading of js9-allinone.js into a Jupyter cell never allowed connection to the js9 helper. The problem is that the browser makes a runtime request for the socket.io client javascript code from the js9 helper and Jupyter blocks the request. It gives no error but returns a null string instead of code. Since the request appears to be successful, JS9 goes ahead and tries to use the returned null result, which gives the "io is not defined" error shown above. If I modify the request to ask for the socket.io code as text instead of as javascript, I do get a CORS error from the Jupyter server. I have no idea why Jupyter throws a CORS erorr, since it is using localhost for its server and I am using localhost for the JS9 helper, so I think this is an issue best taken up by our Jupyter experts.

That said, loading js9-allineone.js works EXCEPT that, as @o-smirnov reported and I misunderstood, the menus are stuck in the upper left corner. I can look into this later.

To make use of a js9 helper on a remote server, it therefore is currently necessary to use an iframe, as was the case previously. This appears to work. I can load local files, then upload them into the server, and run back-end analysis on the uploaded file. The menus are almost in the right place (a little shifted to the right), and I will look into this later.

Why was @o-smirnov getting the "io is not defined" error when loading js9-allinone.js? I can only guess that js9prefs.js was being loaded as well, which overrode the default of not connecting to a helper.

Below is a summary of the code I entered into a Jupyter cell and the results I found. I will look into the menu problem in the next day or so. Assuming I can find the problem it will undoubtedly require code changes to JS9.

# direct load of local js9-allinone.js:
# results: open local file works, no remote analysis, menus stuck in upper left
%%html
<div class="JS9Menubar"></div>
<div class="JS9"></div>
<div style="margin-top: 2px;"><div class="JS9Colorbar"></div></div>
<link type="text/css" rel="stylesheet" href="http://localhost/~eric/js9dev/js9-allinone.css">
<script type="text/javascript" src="http://localhost/~eric/js9dev/js9-allinone.js"></script>

# direct load of main web site js9-allinone.js:
# results: open local file works, no remote analysis, menus stuck in upper left
%%html
<div class="JS9Menubar"></div>
<div class="JS9"></div>
<div style="margin-top: 2px;"><div class="JS9Colorbar"></div></div>
<link type="text/css" rel="stylesheet" href="https://js9.si.edu/jupyter/js9-allinone.css">
<script type="text/javascript" src="https://js9.si.edu/jupyter/js9-allinone.js"></script>

# iframe of local web page
# results: open local file works, remote analysis works, menus OK
%%html
<iframe src="http://localhost/~eric/index.html" width=1000 height=750></iframe>

# iframe of main web site web page
# results: open local file works, remote analysis works, menus OK
%%html
<iframe src="http://js9.si.edu" width=1000 height=750></iframe>

# iframe of main web site subsidiary web page
# results: open local file works, remote analysis works incl upload, menus OK
%%html
<iframe src="http://js9.si.edu/js9/js9.html" width=1000 height=750></iframe>
ericmandel commented 6 years ago

I have more or less fixed position of the JS9 menus. I'm not sure why Jupyter is processing the wrong position values, and so I had to use a more basic positioning technique. It seems to work OK. It's updated in GitHub as well as the main web site.

Just another thing for a Jupyter expert to look into ... some day ...

o-smirnov commented 6 years ago

Thanks, @ericmandel. The iframe approach works for me -- at least to load JS9 from the main website -- and I confirm the menus are in the right place. The CORS error must be a Jupyter issue -- at your suggestion I tried SimpleHTTPServer, and my local install of JS9 starts up fine. So I'll take that up with the Jupyter people.

However, even with SimpleHTTPServer, I still can't get the helper to load up a server-side FITS file. The JS9 display just shows a spinning wheel, while the helper process prints out:

socket.io:socket dispatching an event ["loadproxy",{"cmd":"js9Xeq loadproxy ./3C147-CD-LO-spw0-s7-lwimager.fullrest.fits","cookie":"_xsrf=2|89506d0f|3a80c841be4330ee255e237b763d1d24|1530023674","dataPath":"$HOME/Desktop:$HOME/data:.:/.../../"},null] +0ms
ERROR:  uncaughtException: %s [%s] [TypeError: arr.includes is not a function] TypeError: arr.includes is not a function
    at getDataPath (/home/oms/radiopadre/js9-www/js9Helper.js:482:15)
    at execCmd (/home/oms/radiopadre/js9-www/js9Helper.js:608:26)
    at Socket.xfunc (/home/oms/radiopadre/js9-www/js9Helper.js:804:2)
    at emitTwo (events.js:87:13)
    at Socket.emit (events.js:172:7)
    at /home/oms/radiopadre/js9-www/node_modules/socket.io/lib/socket.js:514:12
    at nextTickCallbackWith0Args (node.js:419:9)
    at process._tickCallback (node.js:348:13)  [2018/07/04, 11:56:05]

3C147-CD-LO-spw0-s7-lwimager.fullrest.fits in there is the name of the FITS file, with the helper running in the same directory as that file...

o-smirnov commented 6 years ago

OK, I worked around that error by adding "dataPathModify": false to js9Prefs.json. Now stuck on:

  socket.io:socket dispatching an event ["loadproxy",{"cmd":"js9Xeq loadproxy 3C147-CD-LO-spw0-s7-lwimager.fullrest.fits","cookie":"_xsrf=2|89506d0f|3a80c841be4330ee255e237b763d1d24|1530023674","dataPath":"$HOME/Desktop:$HOME/data:.:/.../../"},null] +0ms
exec: /home/oms/radiopadre/js9-www/analysis-wrappers/js9Xeq [loadproxy,3C147-CD-LO-spw0-s7-lwimager.fullrest.fits]  [2018/07/04, 12:36:17]
  socket.io:socket sending ack [{"stdout":null,"stderr":"ERROR: could not retrieve: 3C147-CD-LO-spw0-s7-lwimager.fullrest.fits\n","errcode":1,"encoding":"ascii"}] +102ms

Reading the documentation (and looking at js9Xeq), it dawned on me that LoadProxy() doesn't quite do what I want anyway. I'm trying to do something simple -- my FITS files are already present server-side -- I don't need the helper to download them first (and I certainly don't want them removed afterwards). Is this a possibility at all?

o-smirnov commented 6 years ago

OK I have a solution for the CORS error, only to run into another problem further on. I'm going to open separate issues for separate problems now, because this discussion is getting a bit too multithreaded....

ericmandel commented 6 years ago

[TypeError: arr.includes is not a function]

Your version of Node.js is very old and does not support newer javascript capabilities. If you upgrade to Node.js v6 or above (Node v8 is current), this error will go away.

ericmandel commented 6 years ago

OK, I worked around that error by adding "dataPathModify": false to js9Prefs.json

What you did was NULL out the data path used by JS9 to find the data file, so its expected that you will not find the data.

I'm trying to do something simple -- my FITS files are already present server-side -- I don't need the helper to download them first

Yes, if the files are already on the server, you can just use JS9.Load() to load them. No need for LoadProxy, which uses wget or curl to retrieve a file from a different server .... this technique is needed to avoid CORS problems, since the display software and the data must originate on the same server.

o-smirnov commented 6 years ago

If you upgrade to Node.js v6 or above (Node v8 is current), this error will go away.

OK, that was simple enough. Turns out that on Ubuntu, node is the legacy v6 version, and nodejs is the v8 version. Running the helper under nodejs indeed makes this error go away.

ericmandel commented 6 years ago

Good, I'll update the documentation to reflect the minimum version needed.

o-smirnov commented 6 years ago

Yes, if the files are already on the server, you can just use JS9.Load() to load them. No need for LoadProxy

Thanks! Looks like I've been labouring under some misapprehensions. I've realized now that what I'm really after is the fits2fits capability described in https://js9.si.edu/js9/help/repfile.html. Is there a way to ask the helper to start with a server-side FITS file (bypassing wget and curl), and generate a representation file?

ericmandel commented 6 years ago

Yes, you just have to turn on fits2fits. You can actually do this on a per-FITS basis in the JS9.Load command itself:

    JS9.Load("foo.fits", {fits2fits: true})

or you can add it to js9prefs.js to make it site-wide:

    "fits2fits": true

Using js9prefs.js in Jupyter, you'll need to turn off the helper and, as we are learning, probably turn off wasm as well (doesn't look like Jupyter deals with wasm properly, but I'm still looking).

You also might want to manipulate the global property that sets the size of the representation image:

image: {xdim: 2048, ydim: 2048, bin: 1},

Depending on what your data look like, you might want to change the image size (extraction from the center of the image) and/or binning factor. For example, Chandra X-ray data usually only needs the center, so we often leave the image dimensions alone and up the bin factor to make the transferred image smaller.

o-smirnov commented 6 years ago

Using js9prefs.js in Jupyter, you'll need to turn off the helper and

I'm confused though -- if I turn off the helper, how do representation images get made? It has to happen on the server side, but without the helper, who's to initiate that process?

If I modify the request to ask for the socket.io code as text instead of as javascript, I do get a CORS error from the Jupyter server. I have no idea why Jupyter throws a CORS erorr, since it is using localhost for its server and I am using localhost for the JS9 helper, so I think this is an issue best taken up by our Jupyter experts.

Could you please try it with the workaround in #3?

ericmandel commented 6 years ago

We both getting confused! and we need to distinguish carefully between the case of using an iframe and that of adding html directives directly into the cell. I thought you were getting the wasm error when adding code directly into the cell. This should not happen with an iframe, since Jupyter is not loading JS9 files directly. So wasm should not be used by JS9 when entering html directive into a cell. It's use should be fine in an iframe.

If this is not the case, please let me know!

But if it is the case, then yes, you need an iframe so that you can utilize the js9 helper to perform the fits2fits conversion.

o-smirnov commented 6 years ago

If this is not the case, please let me know!

Not the case. Sorry, I'm pursuing so many leads at once that it has gotten quite confusing. Let me try to clarify. So, I have Jupyter's Tornado server running on port 8888, serving me a notebook. I also have a separate SimpleWebServer instance listening on port 12000. I have tried different ways to run JS9:

So, as I understand it, we have three problems remaining:

ericmandel commented 6 years ago

@o-smirnov I am working on the Tornado server problems but it might take a while to get back to you. The use of --NotebookApp.allow_origin='*' did not allow the js9 helper's client socket io code to be retrieved by the Chrome or FF browser. I still get a CORS error, but I am now wondering whether this is an error from socket.io instead of Jupyter. I have to look into this and it will take a bit of time.

I have turned off wasm in the Jupyter environment but have not updated into GitHub. I need to understand all of this better before I commit. I don't understand what Jupyter is doing so that we get wasm errors in an iframe.

ericmandel commented 6 years ago

I still don't understand something about the helper, hence my earlier question, "Is there a way to ask the helper to start with a server-side FITS file (bypassing wget and curl), and generate a representation file from that?"

When fits2fits is enabled, either site-wide in js9prefs.js or by adding {fits2fits:true}) to a JS9.Load() call or a URL containing a JS9.Load() call, the browser knows to ask the js9 helper to extract a smaller file for display from the original file (which is one the server).

Have a look at the URLs in this demo:

https://js9.si.edu/js9/js9large.html

(The fits2fits property accepts conditional as well as true or false, but it sounds like you just want to set it for all files.)

o-smirnov commented 6 years ago

Thanks very much! OK, I think I understand the helper side of things, and I've got the SimpleHTTPServer workaround to tide me over in the meantime. Let me know if there's anything I can do to help on the Tornado side, not that I understand much of it...

ericmandel commented 6 years ago

What would be useful, of course, is for a Jupyter expert to dig into how Jupyter handles javascript. I'm running Jupyter 4.4.0 (which miniconda recently installed for me) and I see on the first page of chapter 7 of the 4.4.1 doc:

https://media.readthedocs.org/pdf/jupyter-notebook/4.x/jupyter-notebook.pdf

the statement:

• Untrusted Javascript is never executed

Is that why we can't retrieve the client socketio javascript code from the js9 helper? And if so, is there any remedy? Or will we never be able to retrieve that script and connect to the helper? It would be most great if someone could look into the Jupyter side of things ...

o-smirnov commented 6 years ago

Well, it also says later on, "Any output generated during an interactive session is trusted." So as far as I understand it, it doesn't (or doesn't mean to) sanitize any JS in our scenario. In fact no jupyter widgets or any such thing would would work if it did do that!

(Where the trust restrictions kick in is when you try to load an existing notebook that already contains saved output from its cells...)

ericmandel commented 6 years ago

But what we are seeing is that JS9 makes a run-time XHR request of the js9 helper for the socket.io client javascript, and that request returns successfully ... but with a null string ... as if "someone" deleted the retrieved javascript. This is different from the cell loading some javascript, which we know does work.

ericmandel commented 6 years ago

the good news: I have made some minor changes to JS9 to trap a few CORS errors triggered by use of the Tornado web server and I can now enter the following into a cell and have everything work correctly:

%%html
<iframe src="http://localhost:8888/files/js9.html" width=1000 height=750></iframe>

To do this, you git pull the new code, and then manually turn off wasm in the js9Prefs.json file:

    useWasm: false

This requirement seems to be due to Jupyter doing something to the wasm file, but I have no idea what that is. I see very little mention of using wasm with Jupyter, so I don't know whether it is actually supported or not.

With this change, restart the helper, load the iframe into a cell, and ... in my case at any rate, the browser connects to the helper and I can load files, drag/drop files, do server-based analysis etc.

It would be good to verify that you can do this as well.

the bad news: when entering html/js/css directly into a cell, I simply cannot get Tornado to return anything but a null string when JS9 makes an XHR request for the socket.io javascript code. I added CORS to the helper so that I was running "allow CORS" at both ends, and the retrieved data is always null. I cannot but believe that Jupyter is scrubbing the code for some reason and I don't know what do to about it.

Once you have a helper running successfully, we can tackle any fits2fits problems that arise. I know it's in use in the field, but of course there could be a bug ... or more Jupyter nuances.

o-smirnov commented 6 years ago

Thanks, this is definite progress! I'll verify tomorrow when I'm back at a keyboard.

On Wed, 04 Jul 2018, 21:39 Eric Mandel, notifications@github.com wrote:

the good news: I have made some minor changes to JS9 to trap a few CORS errors triggered by use of the Tornado web server and I can now enter the following into a cell and have everything work correctly:

%%html

To do this, you git pull the new code, and then manually turn off wasm in the js9Prefs.json file:

useWasm: false

This requirement seems to be due to Jupyter doing something to the wasm file, but I have no idea what that is. I see very little mention of using wasm with Jupyter, so I don't know whether it is actually supported or not.

With this change, restart the helper, load the iframe into a cell, and ... in my case at any rate, the browser connects to the helper and I can load files, drag/drop files, do server-based analysis etc.

It would be good to verify that you can do this as well.

the bad news: when entering html/js/css directly into a cell, I simply cannot get Tornado to return anything but a null string when JS9 makes an XHR request for the socket.io javascript code. I added CORS to the helper so that I was running "allow CORS" at both ends, and the retrieved data is always null. I cannot but believe that Jupyter is scrubbing the code for some reason and I don't know what do to about it.

Once you have a helper running successfully, we can tackle any fits2fits problems that arise. I know it's in use in the field, but of course there could be a bug ... or more Jupyter nuances.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/gijzelaerr/js9notebook/issues/2#issuecomment-402548545, or mute the thread https://github.com/notifications/unsubscribe-auth/AGK5vwxfo1O22XfRtZrbGQrCKWn-ro6Wks5uDRnlgaJpZM4Gw5JX .

ericmandel commented 6 years ago

I opened an issue regarding wasm and jupyter here:

https://github.com/ipython/ipython/issues/11216

I'll do the same for the xhr/socket.io problem tomorrow, almost done with the illustrative test case.

o-smirnov commented 6 years ago

It would be good to verify that you can do this as well.

Confirmed, this now works for me. In the interests of un-confusing this discussion, I'll open another issue for the xhr/socket.io problem. This way we have separate tickets to discuss the outstanding problems.

o-smirnov commented 6 years ago

@ericmandel you can probably close this issue... all the remaining stuff has its own threads now.