nglviewer / nglview

Jupyter widget to interactively view molecular structures and trajectories
http://nglviewer.org/nglview/latest/
Other
821 stars 134 forks source link

Idea about displaying in webpage #678

Closed hainm closed 7 years ago

hainm commented 7 years ago

Assuming NGL can be deserialized.

Backend

view._ngl_deserialize = True
# view._serialized_stage

-> This will trigger this.model.set(NGL.deserialize(this.model.stage), "_serialized_stage") -> view._serialized_stage will be updated in backend.

Should update render method

            this.displayed.then(function() {
            ...
                if (this.model.get("_ngl_serialize")){
                    this.stage.deserialize(this.model.get("_serialized_stage"));
                }
            }.bind(this));

So when we use "Embed Widgets" in notebook, the properties

view._ngl_deserialize
view._serialized_stage

will be saved in output html page, which are sufficient to "render"

this.stage.deserialize(this.model.get("_serialized_stage"));
hainm commented 7 years ago

ping @arose: any timeline for NGL.Stage deserialization? Would be great if we can a show case here: http://jupyter.org/widgets.html

hainm commented 7 years ago

Another work around is to save all commands sent from backend to frontend via view._ngl_msg_archive,

then in frontend

            if (this.model.get("_ngl_serialize")){
                var ngl_msg_archive = this.model.get("_ngl_msg_archive");
                _.each(ngl_msg_archive, function(msg){
                    that.on_msg(msg);
                });
            }
hainm commented 7 years ago

uhm, one of the messages is 'loadFile', which is async. Clearly that's why I got error

nglview-js-widgets.js:1027 makeRepresentation: object [object Object] unknown
nglview-js-widgets.js:1027 Uncaught (in promise) TypeError: Cannot read property 'type' of 
undefined

In the backend, we handle that by put other commands in the queue, only execute if frontend sends signal OK.

hainm commented 7 years ago

A possible syntax for notebook

with view.deserialize():
    view.write_html(filename)
hainm commented 7 years ago

@arose I need your advice here:

Given that I have a list of commands

['loadFile', cm1, cm2, 'loadFile', cm3]

What's reliable code to reconstruct NGL.Stage?

stage.loadFile(...) # async
stage.cm1(...)
stage.cm2(...)
stage.loadFile(...) # async
stage.cm3
hainm commented 7 years ago

A possible syntax for notebook

with view.deserialize():
view.write_html(filename)

Note to myself: or we can just overwrite view.get_state method by updating

{_ngl_serialize: True,
 _ngl_msg_archive: [...]}

Then click Embed Widgets will do the rest.

hainm commented 7 years ago

uhm, I am over thinking.

Given a list of commands, we just need to extract all loadFile commands, then using Promise

Promise.all([
    stage.loadFile(...),
    stage.loadFile(...),
]).then(function(ol){
    stage.setParameters(...);
    // and update representations from view._ngl_repr_dict
})
hainm commented 7 years ago

wow, make that work (in serialization branch):

Notebook:

screen shot 2017-08-17 at 2 04 27 am

Then, choose "Widgets" -> "Embed Widgets" -> "Copy to Clipboard" -> Open any text editor, paste the content, save to index2.html -> Open that file with any web browser.

Here we go

screen shot 2017-08-17 at 2 01 38 am
hainm commented 7 years ago

Next: display trajectory. (should be small).

Issue

hainm commented 7 years ago

Update others parameters

hainm commented 7 years ago

@arose

screen shot 2017-08-17 at 2 26 20 am screen shot 2017-08-17 at 2 26 37 am
hainm commented 7 years ago

done.