In [15]:
import ipywidgets as widgets
import json
import time
import os
from IPython.display import display, HTML
from traitlets import Int, Unicode, observe

two javascript libraries which may not always be available. detect that if so.


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)


setHeight(600) 

In [8]:
print(app.getChromLocString())


5:88,903,464-88,907,108

In [9]:
import zmq

start the trenaGeneModel microservice

cd ~/github/projects/examples/microservices/trenaGeneModel/
R -f trenaGeneModel.R  

In [10]:
socketContext = zmq.Context()
socket = socketContext.socket(zmq.REQ)
socket.connect("tcp://localhost:%s" % '5557')
socket


Out[10]:
<zmq.sugar.socket.Socket at 0x10694f8e8>

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()))


{"status": "request", "cmd": "ping", "callback": "", "payload": ""}
{'status': ['result'], 'cmd': {}, 'callback': [''], 'payload': ['pong']}

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 [ ]: