In [1]:
import ipywidgets as widgets
import json
import time
import os
from IPython.display import display, HTML
from traitlets import Int, Unicode, observe
In [2]:
import requests
assert(requests.get('http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.js').status_code == 200)
assert(requests.get('http://igv.org/web/release/1.0.6/igv-1.0.6.js').status_code == 200)
In [ ]:
display(HTML('<link rel="stylesheet" type="text/css" href="//igv.org/web/release/1.0.6/igv-1.0.6.css">'))
In [4]:
class TabsWidget(widgets.DOMWidget):
_view_name = Unicode('TabsView').tag(sync=True)
_view_module = Unicode('tabsDemo').tag(sync=True)
frameHeight = Int(300).tag(sync=True)
_chromLocString = "chr1:0-0";
_rawMessage = "";
_incomingMessage = {};
msgFromKernel = Unicode("{}").tag(sync=True)
msgFromBrowser = Unicode("{}").tag(sync=True)
status = "initial status message\n"
# ensure that any ensuing message is seen as novel in the browser
# the message (a json-ified string) is a mutable traitlet. the browser only sees
# the message if it changes
def _sendResetMessageToBrowser(self):
self.msgFromKernel = json.dumps({"cmd": "cleanSlate", "status": "nop", "callback": "", "payload": ""});
def setHeight(self, height):
print("setHeight(%d) "% height)
self.frameHeight = height
def getChromLocString(self):
return self._chromLocString
def ping(self):
self._sendResetMessageToBrowser()
self.msgFromKernel = json.dumps({"cmd": "ping", "status": "request", "callback": "", "payload": ""});
def deleteGraph(self):
self._sendResetMessageToBrowser()
self.msgFromKernel = json.dumps({"cmd": "deleteGraph", "status": "request", "callback": "", "payload": ""});
def addGraph(self, gjson):
self._sendResetMessageToBrowser();
self.msgFromKernel = json.dumps({"cmd": "addGraph", "status": "request",
"callback": "", "payload": gjson});
def fitSelected(self, margin=50):
self._sendResetMessageToBrowser();
self.status += "entering fitSelected (%d)\n" % margin
self.msgFromKernel = json.dumps({"cmd": "fitSelected", "status": "request", "callback": "", "payload": margin});
def fit(self, margin=50):
self._sendResetMessageToBrowser();
self.status += "entering fit (%d)\n" % margin
self.msgFromKernel = json.dumps({"cmd": "fit", "status": "request", "callback": "", "payload": margin});
def availableLayouts(self):
self._sendResetMessageToBrowser();
return(["grid", "null", "random", "cose", "circle", "concentric", "breadthfirst"]);
def layout(self, name):
self._sendResetMessageToBrowser();
self.msgFromKernel = json.dumps({"cmd": "layout", "status": "request", "callback": "", "payload": name});
def tfGridLayout(self):
self._sendResetMessageToBrowser();
self.msgFromKernel = json.dumps({"cmd": "tfGridLayout", "status": "request", "callback": "", "payload": ""});
def selectedNodeGridLayout(self, name):
self._sendResetMessageToBrowser();
self.msgFromKernel = json.dumps({"cmd": "selectedNodeGridLayout", "status": "request", "callback": "", "payload": ""});
def loadNetworkStyleFile(self, filename):
if(not os.path.isfile(filename)):
print("file '%s' not found" % filename)
return;
self._sendResetMessageToBrowser();
self.msgFromKernel = json.dumps({"cmd": "loadNetworkStyleFile", "status": "request", "callback": "",
"payload": filename});
@observe('msgFromBrowser')
def msg_arrived(self, change):
#self.status += "msgFromBrowser has arrived: %f\n" % time.time()
self._rawMessage = change['new']
#self.status += "rawMessage: %s\n" % self._rawMessage
self._incomingMessage = json.loads(self._rawMessage)
cmd = self._incomingMessage["cmd"]
#self.status += "cmd: %s\n" % cmd
if(cmd == "updateChromLocString"):
self._chromLocString = self._incomingMessage["payload"]
else:
self.status += "unrecognized cmd: '%s'" % cmd
display(HTML(data="""
"""))
In [5]:
%%javascript
"use strict"
require.config({
paths: {'jquery' : 'http://code.jquery.com/jquery-1.12.4.min',
'jquery-ui' : 'http://code.jquery.com/ui/1.12.1/jquery-ui.min',
'cytoscape' : 'http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape',
'bootstrap' : 'http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min',
'igv' : 'http://igv.org/web/release/1.0.6/igv-1.0.6',
'three' : 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three',
'app3d' : 'http://localhost:9998/files/three/js/app3d'
},
shim: {'bootstrap': {'deps' : ['jquery']},
'igv': {'deps' : ['jquery', 'jquery-ui', 'bootstrap']},
'three': {'exports': 'THREE'}
}
});
require.undef('tabsDemo')
define('tabsDemo', ["jupyter-js-widgets", "jquery", "jquery-ui", "cytoscape", "igv", 'three', 'app3d'],
function(widgets, $, ui, cytoscape, igv, THREE, app3d) {
var TabsView = widgets.DOMWidgetView.extend({
initialize: function() {
window.tabsWidget = this;
this.options = {}
this.chromLocString = "";
console.log("constructing TabsView");
this.frameHeight = "800px";
window.cyInitialized = false;
},
showDivSize: function(divName){
var width = Math.round($("#" + divName).width())
var height = Math.round($("#" + divName).height())
console.log(divName + ": " + width + " x " + height);
},
resizeHandler: function(){
//window.tabsWidget.showDivSize("masterTabsDiv");
$("#cyOuterDiv").height($("#masterTabsDiv").height() * 0.95);
$("#cyDiv").height($("#cyOuterDiv").height() - 25);
$("#threeDiv").height($("#masterTabsDiv").height() * 0.90);
//window.tabsWidget.showDivSize("cyOuterDiv");
//window.tabsWidget.showDivSize("cyMenubarDiv");
//window.tabsWidget.showDivSize("cyDiv");
//window.tabsWidget.showDivSize("igvDiv");
},
createMasterTabsDiv: function(){
var masterTabsDiv = $("<div id='masterTabsDiv' style='border:1px solid gray; height: 1200px; width: 97%'></div>");
var list = $("<ul/>");
list.append("<li><a href='#tab-2'>igv</a></li>");
list.append("<li><a href='#tab-1'>cytoscape</a></li>");
list.append("<li><a href='#tab-3'>three</a></li>");
masterTabsDiv.append(list);
var tab2 = $("<div id='tab-1'></div>");
tab2.append("<div id='cyOuterDiv' style='border:1px solid red; margin: auto; width: 98% height: 95%;'>" +
"<div id='cyMenubarDiv' style='background-color: lightgray; height: 25px'>" +
"<button id='cyFitButton'>Fit</button>" +
"<button id='cyFitSelectedButton'>Fit Selected</button>" +
"<button id='cySFNButton'>SFN</button>" +
"<button id='cyHideUnselectedButton'>Hide Unselected</button>" +
"<button id='cyShowAllButton'>Show All</button>" +
"</div>" +
"<div id='cyDiv' style='background-color: lightgray; border:1px solid green; margin: auto; width: 100%; height: 98%'></div> </div>");
var tab1 = $("<div id='tab-2'></div>");
tab1.append("<div id='igvDiv' style='border:1px solid green; height:1000px;'></div>");
var tab3 = $("<div id='tab-3'>contents 3</div>");
tab3.append("<div id='threeDiv' style='border:1px solid magenta; margin: auto; width: 98% height: 500px;'></div>");
masterTabsDiv.append(tab1);
masterTabsDiv.append(tab2);
masterTabsDiv.append(tab3);
return(masterTabsDiv);
},
getCyOptions: function(){
console.log("entering getCyOptions");
debugger;
var value = {container: $("#cyDiv"),
elements: {nodes: [{data: {id:'a'}}],
edges: [{data:{source:'a', target:'a'}}]},
style: cytoscape.stylesheet()
.selector('node').style({'background-color': '#d22',
'label': 'data(id)',
'text-valign': 'center',
'text-halign': 'center',
'border-width': 1})
.selector('edge').style({'line-color': 'black',
'target-arrow-shape': 'triangle',
'target-arrow-color': 'black',
'curve-style': 'bezier'})
};
console.log("about to leave getCyOptions")
return(value);
}, // getCyOptions
getIgvOptions: function(){
var igvOptionsLocal = {locus: "7:101,165,560-101,165,630", // 5:88,621,548-88,999,827",
reference: {id: "geneSymbols_hg38",
fastaURL: "http://pshannon.systemsbiology.net/genomes/human_g1k_v37_decoy.fasta",
cytobandURL: "http://pshannon.systemsbiology.net/annotations/b37_cytoband.txt"
},
tracks: [
{name: 'Gencode v24',
url: "http://pshannon.systemsbiology.net/hg38/gencode.v24.annotation.sorted.gtf.gz",
indexURL: "http://pshannon.systemsbiology.net/hg38/gencode.v24.annotation.sorted.gtf.gz.tbi",
format: 'gtf',
visibilityWindow: 2000000,
displayMode: 'EXPANDED'
},
{name: 'geneSymbols_hg38',
url: 'http://pshannon.systemsbiology.net/hg38/geneSymbolSearch.bed',
indexed: false,
searchable: true,
//visibilityWindow: 5000000,
displayMode: 'COLLAPSED',
color: "#448844"
},
{name: "igap gwas",
url: 'http://pshannon.systemsbiology.net/hg38/variants/igap.bed',
indexed: false,
searchable: true,
//visibilityWindow: 5000000,
displayMode: 'EXPANDED',
color: "#884444"
}
]
}; // igvOptionsLocal
return(igvOptionsLocal);
}, // getIgvOptions
initializeNewThreeTab: function(){
window.app3d = app3d;
app3d.init("threeDiv");
var data = [{"chr":6,"pos":147596,"an":1,"af":0.9812,"EC1":0.0244},
{"chr":6,"pos":148039,"an":1,"af":0.7887,"EC1":-0.1367}];
var data3 = [{"gene":"ADNP","x":-146.0568,"y":-0.7765,"z":1.345},
{"gene":"ADNP2","x":-111.9405,"y":0.7206,"z":1.9047},
{"gene":"ALX1","x":51.0562,"y":-9.3092,"z":-15.5825},
{"gene":"ALX3","x":-38.909,"y":-2.9967,"z":1.2376},
{"gene":"ALX4","x":-17.7929,"y":-2.9019,"z":-6.0279},
{"gene":"ARGFX","x":87.2175,"y":7.2355,"z":-7.2452},
{"gene":"ARX","x":-91.302,"y":5.8996,"z":0.9547},
{"gene":"CRX","x":24.0127,"y":-1.8842,"z":1.1204},
{"gene":"DPRX","x":96.4716,"y":-11.5378,"z":13.6378},
{"gene":"DRGX","x":-30.3606,"y":20.0352,"z":0.1661},
{"gene":"DUXA","x":124.1735,"y":1.6056,"z":1.2608},
{"gene":"ELF3","x":6.4602,"y":2.3951,"z":2.9274},
{"gene":"ESX1","x":125.4266,"y":2.1301,"z":2.1979},
{"gene":"GSC","x":101.5726,"y":-6.5466,"z":-5.9331},
{"gene":"GSC2","x":113.1012,"y":4.1633,"z":4.064},
{"gene":"HESX1","x":-21.7646,"y":-0.5798,"z":4.4957},
{"gene":"HOMEZ","x":-90.9856,"y":-2.7474,"z":1.2747},
{"gene":"HOPX","x":-155.0937,"y":4.4173,"z":-0.9517},
{"gene":"ISX","x":121.934,"y":2.3002,"z":0.6731},
{"gene":"LEUTX","x":125.4103,"y":1.7299,"z":2.0273},
{"gene":"MEF2C","x":-168.1081,"y":10.322,"z":2.2409},
{"gene":"MIXL1","x":29.8232,"y":5.892,"z":5.236},
{"gene":"NOBOX","x":114.7024,"y":4.3831,"z":2.4121},
{"gene":"OTP","x":73.4485,"y":22.8675,"z":1.6014},
{"gene":"OTX1","x":-61.1505,"y":-1.0486,"z":-1.7832},
{"gene":"OTX2","x":91.1536,"y":-16.412,"z":5.2518},
{"gene":"PHOX2A","x":85.9395,"y":0.0448,"z":-10.3375},
{"gene":"PHOX2B","x":123.2999,"y":1.5495,"z":4.2616},
{"gene":"PITX1","x":86.3081,"y":-14.9184,"z":-4.9912},
{"gene":"PITX2","x":113.9095,"y":3.6351,"z":-1.4579},
{"gene":"PITX3","x":98.6208,"y":3.3063,"z":4.4485},
{"gene":"PROP1","x":54.8345,"y":11.5046,"z":-22.5947},
{"gene":"PRRX1","x":-97.6001,"y":-7.997,"z":-0.1716},
{"gene":"PRRX2","x":-2.1381,"y":-7.3584,"z":-5.464},
{"gene":"RAX","x":98.7371,"y":-21.1732,"z":20.4459},
{"gene":"RAX2","x":32.2993,"y":-5.3922,"z":-13.5179},
{"gene":"RHOXF1","x":-17.3206,"y":2.2535,"z":-0.6599},
{"gene":"RHOXF2","x":98.8198,"y":-1.538,"z":0.2752},
{"gene":"RHOXF2B","x":117.5179,"y":6.9199,"z":4.6329},
{"gene":"SEBOX","x":87.627,"y":3.701,"z":-6.6413},
{"gene":"SHOX","x":79.1686,"y":-6.9527,"z":-11.0102},
{"gene":"SHOX2","x":60.181,"y":7.1496,"z":16.6654},
{"gene":"TPRX1","x":84.3702,"y":-3.7428,"z":-17.4296},
{"gene":"TSHZ1","x":-129.1469,"y":-0.1712,"z":-0.473},
{"gene":"TSHZ2","x":-101.2699,"y":7.1558,"z":1.7648},
{"gene":"TSHZ3","x":-105.0179,"y":4.4191,"z":0.3811},
{"gene":"UNCX","x":111.1621,"y":-6.2214,"z":7.1391},
{"gene":"VSX1","x":-64.5455,"y":-4.3236,"z":1.3823},
{"gene":"VSX2","x":36.9045,"y":17.9651,"z":13.514},
{"gene":"ZBTB16","x":-125.9315,"y":-0.172,"z":0.1997},
{"gene":"ZEB1","x":-144.9223,"y":-2.2388,"z":0.2275},
{"gene":"ZEB2","x":-166.8426,"y":-5.2802,"z":3.2249},
{"gene":"ZFHX2","x":-113.4972,"y":-0.5561,"z":-3.1312},
{"gene":"ZFHX3","x":-115.247,"y":-3.7799,"z":-1.7704},
{"gene":"ZFHX4","x":-120.3524,"y":-4.7425,"z":0.162},
{"gene":"ZHX1","x":-140.2198,"y":-3.0202,"z":0.5338},
{"gene":"ZHX2","x":-124.4253,"y":-5.8642,"z":1.7423},
{"gene":"ZHX3","x":-153.7224,"y":-3.5177,"z":0.1432}];
app3d.drawScatterPlot(data3);
app3d.resize();
app3d.animate()
},
render: function() {
var multiWidget = this;
$(window).resize(multiWidget.resizeHandler);
console.log("entering render");
this.listenTo(this.model, 'change:msgFromKernel', this.dispatchRequest, this);
this.masterTabsDiv = this.createMasterTabsDiv();
this.$el.append(this.masterTabsDiv);
this.listenTo(this.model, 'change:frameHeight', this.frameDimensionsChanged, this);
setTimeout(function(){
window.browser = igv.createBrowser($("#igvDiv"), multiWidget.getIgvOptions());
//window.browser.on('locuschange', function(referenceFrame, chromLocString){multiWidget.chromLocString=chromLocString});
window.browser.on('locuschange', function(referenceFrame, chromLocString){
multiWidget.updateChromLocStringToKernel(multiWidget, chromLocString)});
setTimeout(function() {
console.log("about to call tabs()");
$("#masterTabsDiv").tabs({
activate: function(){
console.log("tabs Activate");
console.log("cyInitialized: " + window.cyInitialized);
if(!window.cyInitialized){
cy.fit(200); // condition this on first time display only
window.cyInitialized = true;
}
cy.resize();
}});
$("[href='#tab-2']").trigger("click");
}, 8000);
}, 3000);
setTimeout(function(){
console.log("starting cy creation setTimeout")
console.log(" cyDiv defined? " + $("#cyDiv"));
var options = multiWidget.getCyOptions();
console.log(" after getCyOptions")
console.log(JSON.stringify(options));
window.cy = cytoscape(multiWidget.getCyOptions());
console.log("window.cy created")
$("#cyDiv").height(800);
$("#cyFitButton").click(function(){cy.fit(50)});
$("#cyFitSelectedButton").click(function(){cy.fit(cy.nodes(":selected"), 50)});
$("#cySFNButton").click(function(){cy.nodes(':selected').neighborhood().nodes().select()});
$("#cyHideUnselectedButton").click(function(){cy.nodes(":unselected").hide()});
$("#cyShowAllButton").click(function(){cy.nodes().show(); cy.edges().show()});
cy.fit(100);
multiWidget.initializeNewThreeTab();
multiWidget.resizeHandler();
}, 1000);
}, // render
dispatchRequest: function(){
console.log("dispatchRequest");
var msgRaw = this.model.get("msgFromKernel");
var msg = JSON.parse(msgRaw);
console.log(msg);
console.log("========================");
console.log(this);
switch(msg.cmd) {
case 'ping':
console.log("ping! from the kernel");
break;
case 'deleteGraph':
cy.edges().remove();
cy.nodes().remove();
break;
case 'layout':
var layoutName = msg.payload;
cy.layout({"name": layoutName})
break;
case 'loadNetworkStyleFile':
var styleFile = msg.payload;
this.loadNetworkStyleFile(styleFile);
break;
case 'tfGridLayout':
cy.nodes().filter("[type='TF']").layout({name: "grid"})
break;
case 'selectedNodeGridLayout':
cy.nodes(":selected").layout({name: "grid"})
break;
case 'addGraph':
console.log("--- addGraph")
var jsonGraph = msg.payload;
console.log(jsonGraph)
cy.json(jsonGraph);
cy.fit(100);
$("[href='#tab-1']").trigger("click");
break;
case 'fit':
var margin = msg.payload;
console.log("fit with margin: " + margin)
cy.fit(margin);
break;
case 'fitSelected':
var margin = msg.payload;
console.log("fit with margin: " + margin)
cy.fit(cy.nodes(":selected"), margin);
break;
default:
console.log("unrecognized msg.cmd: " + msg.cmd);
} // switch
},
updateChromLocStringToKernel: function(multiWidget, newString){
console.log("xxx " + newString);
var jsonString = JSON.stringify({cmd: "updateChromLocString",
status: "request",
callback: "",
payload: newString});
multiWidget.model.set("msgFromBrowser", jsonString);
multiWidget.touch()
},
loadNetworkStyleFile: function(filename){
console.log("--- entering loadNetworkStyleFile")
var cyObj = window.cy
var str = window.location.href;
var url = str.substr(0, str.lastIndexOf("/")) + "/" + filename;
url = url.replace("/notebooks/", "/files/");
console.log("--- loadNetworkStyleFile: " + 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);
});
},
frameDimensionsChanged: function(){
console.log("frameDimensionsChanged");
var oldHeight = $("#masterTabsDiv").height()
var oldWidth = $("#masterTabsDiv").width()
var newHeight = this.model.get("frameHeight");
var msg = "<center>tabs demo, height: " + oldHeight + " -> " + newHeight + "</center>";
$("#masterTabsDiv").height(newHeight);
},
});
return {
TabsView: TabsView
};
});
In [6]:
app = TabsWidget()
display(app)
In [7]:
app.deleteGraph()
In [8]:
app.setHeight(1800)
In [9]:
print(app.getChromLocString())
In [10]:
import zmq
In [11]:
socketContext = zmq.Context()
socket = socketContext.socket(zmq.REQ)
socket.connect("tcp://localhost:%s" % '5557')
socket
Out[11]:
In [ ]:
msg = {"cmd": "ping", "status": "request", "callback": "", "payload": ""}
msg_json = json.dumps(msg)
print(msg_json)
socket.send_string(json.dumps(msg))
print(json.loads(socket.recv_string()))
msg = json.dumps({"cmd": "getTestNetwork", "status": "request", "callback": "", "payload": "VGF"}) socket.send_string(msg) gjson = json.loads(socket.recv_string())["payload"] gjson
app.deleteGraph() app.addGraph(gjson)
In [ ]:
region = app.getChromLocString()
targetGene = "VGF"
msg = json.dumps({"cmd": "createGeneModel", "status": "request", "callback": "",
"payload": {"targetGene": targetGene, "footprintRegion": region}})
socket.send_string(msg)
gjson = json.loads(socket.recv_string())["payload"][0]
graphData = json.loads(gjson)
app.deleteGraph()
app.addGraph(graphData)
app.loadNetworkStyleFile("style-purityControlsNodeSize.js")
In [ ]:
graphData = json.loads(gjson)
app.deleteGraph()
app.addGraph(graphData)
app.loadNetworkStyleFile("style-purityControlsNodeSize.js")
In [ ]:
In [ ]:
app.fit()
In [ ]:
app.fitSelected()
In [ ]:
app.selectedNodeGridLayout("foo")
In [ ]:
app.availableLayouts()
In [ ]:
app.layout("grid")
app.layout("cose")
In [ ]: