In [15]:
import ipywidgets as widgets
import json
import time
import os
from IPython.display import display, HTML
from traitlets import Int, Unicode, observe
In [16]:
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 [17]:
display(HTML('<link rel="stylesheet" type="text/css" href="//igv.org/web/release/1.0.6/igv-1.0.6.css">'))
In [11]:
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
In [12]:
display(HTML(data="""
<style>
div#notebook-container { width: 97%; }
div#menubar-container { width: 65%; }
div#maintoolbar-container { width: 99%; }
</style>
"""))
In [ ]:
In [13]:
%%javascript
"use strict"
require.config({
shim: {'bootstrap': {'deps' :['jquery']},
'igv': {'deps' :['jquery', 'jquery-ui', 'bootstrap']}
},
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'
}
});
require.undef('tabsDemo')
define('tabsDemo', ["jupyter-js-widgets", "jquery", "jquery-ui", "cytoscape", "igv"],
function(widgets, $, ui, cytoscape, igv) {
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);
//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>");
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',
//url: 'http://localhost/data/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
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.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 [18]:
app = TabsWidget()
display(app)
In [19]:
app.deleteGraph()
In [21]:
app.setHeight(600)
In [8]:
print(app.getChromLocString())
In [9]:
import zmq
In [10]:
socketContext = zmq.Context()
socket = socketContext.socket(zmq.REQ)
socket.connect("tcp://localhost:%s" % '5557')
socket
Out[10]:
In [11]:
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 [12]:
region = app.getChromLocString()
targetGene = "VGF"
# targetGene = "ABCB1"
targetGene = "MEF2C"
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 [24]:
graphData = json.loads(gjson)
app.deleteGraph()
app.addGraph(graphData)
app.loadNetworkStyleFile("style-purityControlsNodeSize.js")
app.fit()
In [ ]:
In [ ]:
app.fit()
In [ ]:
app.fitSelected()
In [ ]:
app.selectedNodeGridLayout("foo")
In [ ]:
app.availableLayouts()
In [ ]:
app.layout("grid")
app.layout("cose")
In [ ]: