In [470]:
%%javascript
require.config({
paths: {cytoscape: 'http://localhost:8099/js/cytoscape-2.7.10'}
})
In [471]:
import ipywidgets as widgets
import json
from traitlets import Int, Unicode, Tuple, CInt, Dict, validate, observe
class cyjsWidget(widgets.DOMWidget):
_view_name = Unicode('CyjsView').tag(sync=True)
_view_module = Unicode('cyjs').tag(sync=True)
frameWidth = Int(400).tag(sync=True)
frameHeight = Int(300).tag(sync=True)
msgStringFromPython = Unicode("{}").tag(sync=True)
msgStringToPython = Unicode("{}").tag(sync=True)
msg = {};
status = "initial status message\n"
selectedNodes = [];
def setSize(self, width, height):
self.status += "setSize(%d, %d)\n" % (width, height)
self.frameWidth = width
self.frameHeight = height
def fit(self, margin=50):
self.status += "entering fit (%d)\n" % margin
self. msgStringFromPython = json.dumps({"cmd": "fit", "status": "request",
"callback": "", "payload": margin});
def requestSelectedNodes(self):
self.selectedNodes = [];
self.status += "entering requestSelectedNodes\n";
self. msgStringFromPython = json.dumps({"cmd": "getSelectedNodes", "status": "request",
"callback": "", "payload": ""});
def getSelectedNodes(self):
return(self.selectedNodes)
def selectNodes(self, nodes):
self. msgStringFromPython = json.dumps({"cmd": "selectNodes", "status": "request",
"callback": "", "payload": nodes});
def clearSelection(self):
self. msgStringFromPython = json.dumps({"cmd": "clearSelection", "status": "request",
"callback": "", "payload": ""});
@observe('msgStringToPython')
def msg_arrived(self, change):
self.status += "---- python - msg arrived\n"
tmp = change['new']
self.status += "len of tmp: %d\n" % len(tmp)
self.status += "type of tmp: %s\n" % type(tmp)
self.msgStringFromPython = tmp
self.status += "%s\n" % tmp
self.dispatch(self.msgStringFromPython)
def dispatch(self, msgRaw):
msg = json.loads(msgRaw)
self.status += "entering dispatch\n"
self.status += "dispatch this msg: %s\n" % msg
self.status += "msg.cmd: %s\n" % msg["cmd"]
if msg["cmd"] == 'storeSelectedNodes':
self.status += "storing selected nodes to self.selectedNodes %s\n" % msg["payload"]
self.selectedNodes = msg["payload"]
elif msg["cmd"] == 'clearCircles':
self.circles = []
else:
print("unknown cmd: %s" % msg["cmd"])
In [476]:
%%javascript
"use strict";
require.undef('cyjs');
define('cyjs', ["jupyter-js-widgets", "cytoscape"], function(widgets, cytoscape) {
var CyjsView = widgets.DOMWidgetView.extend({
initialize: function() {
this.circles = [];
this.circleCount = 0;
this.options = {};
this.msg = "empty in javascript";
this.msgStringFromPython = "";
this.defaultHeight = "800px";
this.defaultWidth = "1000px";
},
createDiv: function(){
var outerDiv = $("<div id='cyOuterDiv' style='border:1px solid gray; height: 800px; width: 1000px'></div>");
var toolbarDiv = $("<div id='cyToolbarDiv' style='height: 30px; width: 1000px'></div>");
var cyDiv = $("<div id='cyDiv' style='height: 870px; width: 1000px'></div>");
outerDiv.append(toolbarDiv);
outerDiv.append(cyDiv);
var cyWidget = this;
var fitButton = $("<button>Fit</button>").click(function(){
console.log("Fit!");
console.log("fitButton's notion of this:")
console.log(cyWidget.cy);
cyWidget.cy.fit(50);
});
toolbarDiv.append(fitButton);
var fitSelectedButton = $("<button>Fit Selected</button>").click(function(){
var selectedNodes = cyWidget.cy.filter('node:selected');
if(selectedNodes.length > 0){
cyWidget.cy.fit(selectedNodes, 50);
}
});
toolbarDiv.append(fitSelectedButton);
var sfnButton = $("<button>SFN</button>").click(function(){
cyWidget.cy.nodes(':selected').neighborhood().nodes().select()
});
toolbarDiv.append(sfnButton);
var clearButton = $("<button>Clear</button>").click(function(){
cyWidget.cy.nodes().unselect();
cyWidget.cy.edges().unselect();
});
toolbarDiv.append(clearButton);
return(outerDiv);
},
createCanvas: function(){
var cyjsWidget = this;
console.log("createCanvas notion of this:")
console.log(cyjsWidget);
this.cy = cytoscape({
container: document.getElementById('cyDiv'),
elements: {
nodes: [
{data: {id: 'a', name: 'Node A', type: 'big' }},
{data: {id: 'b', name: 'Node B', type: 'little'}},
],
edges: [
{data: {source: 'a', target: 'b'}},
{data: {source: 'b', target: 'a'}}
]},
ready: function(){
console.log("small cyjs network ready");
console.log("ready's notion of this:")
console.log(this);
cyjsWidget.cy = this;
window.cy = this; // for easy debugging
console.log("ready's notion of cyjsWidget:")
console.log(cyjsWidget);
console.log("calling this.fit")
//cyWidget.cy.fit(100);
cyjsWidget.loadStyle("style.js");
console.log("--- about to call loadGraph")
//cyjsWidget.loadGraph("igap4snpGenesetEnrichment.json");
console.log(" back from loadGraph")
} // ready
})},
loadStyle: function(filename){
var cyObj = this.cy;
console.log("cyjsWidget.loadStyle: " + filename)
console.log("loadStyle's notion of this:");
console.log(this);
console.log("loadStyle's notion of cy:");
console.log(cyObj);
var url = window.location.origin + "/files/cyjs/" + filename;
console.log("about to getScript: " + url);
$.getScript(url)
.done(function(script, textStatus) {
console.log(textStatus);
cyObj.style(vizmap);
})
.fail(function( jqxhr, settings, exception ) {
console.log("getScript error trying to read " + filename);
console.log("exception: ");
console.log(exception);
});
},
loadGraph: function(filename){
console.log("entering loadGraph");
var cyObj = this.cy;
var url = window.location.origin + "/files/cyjs/" + filename;
console.log("=== about to getScript on " + url);
$.getScript(url)
.done(function(script, textStatus) {
console.log("getScript: " + textStatus);
console.log("nodes: " + network.elements.nodes.length);
if(typeof(network.elements.edges) != "undefined")
console.log("edges: " + network.elements.edges.length);
cyObj.add(network.elements); // no positions yet
cyObj.nodes().map(function(node){node.data({degree: node.degree()})});
}) // .done
.fail(function(jqxhr, settings, exception) {
console.log("addNetwork getscript error trying to read " + filename);
});
},
render: function() {
console.log("entering render")
this.$el.append(this.createDiv());
this.listenTo(this.model, 'change:frameWidth', this.frameDimensionsChanged, this);
this.listenTo(this.model, 'change:frameHeight', this.frameDimensionsChanged, this);
this.listenTo(this.model, 'change:msgStringFromPython', this.dispatchRequest, this)
var cyjsWidget = this;
function myFunc(){
cyjsWidget.createCanvas()
}
setTimeout(myFunc, 500);
},
dispatchRequest: function(){
console.log("dispatchRequest");
var msgRaw = this.model.get("msgStringFromPython");
var msg = JSON.parse(msgRaw);
console.log(msg);
console.log("========================");
console.log(this);
switch(msg.cmd) {
case 'fit':
var margin = msg.payload;
console.log("fit with margin: " + margin)
this.cy.fit(margin);
break;
case 'getSelectedNodes':
var selectedNodes = this.cy.filter("node:selected").map(function(node){
return node.data().id});
console.log("-- found these selected nodes: ");
console.log(selectedNodes);
var jsonString = JSON.stringify({cmd: "storeSelectedNodes",
status: "reply",
callback: "",
payload: selectedNodes})
console.log(" *** jsonString: ")
console.log(jsonString);
this.model.set("msgStringToPython", jsonString);
console.log(" after setting 'msgStringToPython");
this.touch();
break;
case 'selectNodes':
var nodeIDs = msg.payload;
console.log("--- selecting these nodes: " + nodeIDs);
if(typeof(nodeIDs) == "string")
nodeIDs = [nodeIDs];
var filterStrings = [];
for(var i=0; i < nodeIDs.length; i++){
var s = '[id="' + nodeIDs[i] + '"]';
filterStrings.push(s);
} // for i
var nodesToSelect = this.cy.nodes(filterStrings.join());
nodesToSelect.select()
break;
case 'clearSelection':
this.cy.nodes().unselect();
break;
default:
console.log("unrecognized msg.cmd: " + msg.cmd);
} // switch
},
frameDimensionsChanged: function(){
console.log("frameDimensionsChanged")
var newWidth = this.model.get("frameWidth");
var newHeight = this.model.get("frameHeight");
console.log("frame: " + newWidth + " x " + newHeight);
$("#cyOuterDiv").width(newWidth);
$("#cyOuterDiv").height(newHeight);
$("#cyToolbarDiv").width(newWidth);
$("#cyDiv").width(newWidth);
$("#cyDiv").height(newHeight - $("#cyToolbarDiv").height());
},
events: {
//"click #svg": "changeHandler"
}
});
return {
CyjsView: CyjsView
};
});
In [477]:
cy = cyjsWidget()
cy
In [478]:
cy.selectNodes("a")
In [479]:
cy.selectNodes("b")
In [480]:
cy.clearSelection()
In [481]:
cy.selectNodes(["a", "b"])
In [482]:
cy.requestSelectedNodes()
In [483]:
cy.getSelectedNodes()
Out[483]:
In [484]:
cy.msgStringToPython
Out[484]:
In [485]:
cy.setSize(300, 300);
In [486]:
cy.fit(200)
# print(cy.status)
In [487]:
cy.setSize(1000, 600);
In [488]:
cy.fit(100)
In [489]:
# print(cy.status)
In [ ]: