In [1]:
%%javascript
require.config({
   paths: {cytoscape: 'http://localhost:8099/js/cytoscape-2.7.10'}
   })



In [2]:
import ipywidgets as widgets
import json
import time
from threading import Thread
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)
    msgFromKernel = Unicode("{}").tag(sync=True)
    msgToKernel = Unicode("{}").tag(sync=True)
    status = "initial status message\n"
    selectedNodes = [];
    incomingMessageArrivedAndParsed = False;
    globalStatus = "blank"

In [3]:
import ipywidgets as widgets
import json
import time
from threading import Thread
from traitlets import Int, Unicode, Tuple, CInt, Dict, validate, observe


class newcyjsWidget(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)
    msgFromKernel = Unicode("{}").tag(sync=True)
    msgToKernel = Unicode("{}").tag(sync=True)
    status = "initial status message\n"
    selectedNodes = [];
    incomingMessageArrivedAndParsed = False;
    globalStatus = "blank"

    #------------------------------------------------------------------------------
    class MyThread(Thread):
       owner = None
       def __init__(self, owner, group=None, target=None, name=None,
                    args=(), kwargs=None, *, daemon=None):
          Thread.__init__(self, group, target, name, args, kwargs, daemon=daemon)
          self.owner = owner

       def run(self):
          maxLoops = 5
          counter = 0
          while((self.owner.incomingMessageArrivedAndParsed == False) and (counter < maxLoops)):
             counter += 1
             print("thread, no message yet, sleeping, loop %d" % counter)
             time.sleep(1.0)
          self.owner.status += "thread owner's selectedNodes: %s\n" % self.owner.selectedNodes;
          self.owner.status += "MyThread ending loop\n";

       def result(self):
          #while(not self.owner.incomingMessageArrivedAndParsed):
          #   time.sleep(0.1)
          return("imaap? %s" % self.owner.incomingMessageArrivedAndParsed)
            
    #------------------------------------------------------------------------------

    def testThread(self):
      for i in range(4):
         threadName = "Thread-%s" % (i + 1)
         mythread = self.MyThread(name=threadName, owner=self)
         mythread.start()
    
    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.msgFromKernel = json.dumps({"cmd": "fit", "status": "request",
                                       "callback": "", "payload": margin});
    def getSelectedNodes(self):
      #self.selectedNodes = [];
      self.incomingMessageArrivedAndParsed = False;
      self.status += "entering getSelectedNodes\n";
      self.msgFromKernel = json.dumps({"cmd": "cleanSlate", "status": "request", "callback": "", "payload":""});
      self.msgFromKernel = json.dumps({"cmd": "getSelectedNodes", "status": "request",
                                       "callback": "", "payload": ""});
      
      observingThread = self.MyThread(name="getSelectedNodes-thread", owner=self)
      print("getSelectedNodes about to start observingThread")
      #observingThread.start()
      #observingThread.join()
      #while(self.incomingMessageArrivedAndParsed == False):
      #   time.sleep(0.5)
      observingThread.start()
      self.status += "getSelectedNodes, observingThread now started: %s\n" %  self.selectedNodes
      self.status += "getSelectedNodes, incomingMessageArrivedAndParsed? %s\n" % self.incomingMessageArrivedAndParsed
      return(observingThread.result())
        #return(self.status)
        
    def selectNodes(self, nodes):
      self.msgFromKernel = json.dumps({"cmd": "selectNodes", "status": "request",
                                       "callback": "", "payload": nodes});
       
    def clearSelection(self):
      self. msgFromKernel = json.dumps({"cmd": "clearSelection", "status": "request",
                                        "callback": "", "payload": ""});
        
    @observe('msgToKernel')
    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.msgToKernel = tmp
        self.status += "%s\n" % tmp
        self.incomingMessageArrived = True
        self.dispatch(self.msgToKernel)
 
    def dispatch(self, msgRaw):
        self.msg = json.loads(msgRaw)
        self.status += "entering dispatch\n"
        self.status += "dispatch this msg: %s\n" % self.msg
        self.status += "msg.cmd: %s\n" % self.msg["cmd"]
        if self.msg["cmd"] == 'storeSelectedNodes':
            self.status += "storing selected nodes to self.selectedNodes %s\n" % msg["payload"]
            self.selectedNodes = msg["payload"]
        elif self.msg["cmd"] == 'clearCircles':
            self.circles = []
        else:
          print("unknown cmd: %s" % self.msg["cmd"])
        self.incomingMessageArrivedAndParsed = True
        
    def getResponse(self):
        return(self.msg["payload"])

In [4]:
%%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.msgToKernel = "";
           this.msgFromKernel = "";
           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);
            console.log("--- about to call loadGraph")
            cyjsWidget.loadGraph("network.json");
            cyjsWidget.loadStyle("style.js");
            console.log("    back from loadGraph")
            cyjsWidget.cy.on("select", function(x){
                var selectedNodeCount = cyjsWidget.cy.nodes(":selected").length;
                var selectedEdgeCount = cyjsWidget.cy.edges(":selected").length;
                console.log("selected nodes: " + selectedNodeCount);
                console.log("selected edges:" + selectedEdgeCount);
                });
            cyjsWidget.cy.on("unselect", function(x){
                var selectedNodeCount = cyjsWidget.cy.nodes(":selected").length;
                var selectedEdgeCount = cyjsWidget.cy.edges(":selected").length;
                console.log("selected nodes: " + selectedNodeCount);
                console.log("selected edges:" + selectedEdgeCount);
                });
            } // 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 str = window.location.href;
           var url = str.substr(0, str.lastIndexOf("/")) + "/" + filename;
           url = url.replace("/notebooks/", "/files/");
           console.log("about to getScript: " + url);
           $.getScript(url)
              .done(function(script, textStatus){
                 console.log("loadStyle: " + textStatus);
                 cyObj.style(vizmap);
                 })
             .fail(function(jqxhr, settings, exception){
                console.log("loadStyle error trying to read " + filename);
                console.log("exception: ");
                console.log(exception);
                });
          },
        
        loadGraph: function(filename){
           console.log("entering loadGraph");
           var cyObj = this.cy;
              // the robust url of a file in the same directory as the notebook is
              // str.substring(0, str.lastIndexOf("/"));
           var str = window.location.href;
           var url = str.substr(0, str.lastIndexOf("/")) + "/" + filename;
           url = url.replace("/notebooks/", "/files/");
           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()})});
                cyObj.fit(150);
                }) // .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:msgFromKernel', this.dispatchRequest, this);
            var cyjsWidget = this;
            function myFunc(){
               cyjsWidget.createCanvas()
               }
            setTimeout(myFunc, 500);
            },

        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 'cleanSlate':
                 console.log("got request to cleanSlate");
                 break;
              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("msgToKernel", jsonString);
                  console.log("    after setting 'msgToKernel");
                  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
           console.log("CONCLUDING dispatchRequest")
           }, 
        
        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 [5]:
cy = newcyjsWidget()
cy

In [6]:
cy.getSelectedNodes();


getSelectedNodes about to start observingThread
thread, no message yet, sleeping, loop 1

In [7]:
cy.getResponse()


thread, no message yet, sleeping, loop 5
Out[7]:
['PLD3']

In [58]:
cy.getResponse()


Out[58]:
['PLD2', 'chr17:4807191-4807191', 'chr19:40348547-40348547']

In [35]:
cy.status = ""
print(cy.getSelectedNodes())


getSelectedNodes about to start observingThread
thread, no message yet, sleeping, loop 1
imaap? False

In [44]:
json.loads(cy.msgToKernel)['payload']
#cy.msgToKernel["payload"]


Out[44]:
['PHB', 'PLD3']

In [27]:
print(cy.status)


entering getSelectedNodes
getSelectedNodes, observingThread now started: []
getSelectedNodes, incomingMessageArrivedAndParsed? False
thread owner's selectedNodes: []
MyThread ending loop
---- python - msg arrived
len of tmp: 77
type of tmp: <class 'str'>
{"cmd":"storeSelectedNodes","status":"reply","callback":"","payload":["MAG"]}
entering dispatch
dispatch this msg: {'status': 'reply', 'cmd': 'storeSelectedNodes', 'payload': ['MAG'], 'callback': ''}
msg.cmd: storeSelectedNodes
storing selected nodes to self.selectedNodes ['MAG']


In [ ]:
cy.incomingMessageArrived = False
cy.incomingMessageArrived

In [ ]:
cy.selectedNodes

Select a SNP in the network view, parse it into a chromosomal location (+/- shoulders), get sequence, run FIMO


In [ ]:
cy.requestSelectedNodes()

In [ ]:
node = cy.getSelectedNodes()[0]
print(node)