Monday 13 August 2012

Back into interacting!

WOW, is been a while!!

I'm the first one to be sorry of no having post recently. I've been busy with the paper I mentioned before and is going to get publish pretty soon! :-) Also, the things I have worked on recently are more improvements than anything else and all around the Interaction Viewer(See this post), so I had the feeling it wasn't enough for a post, however now that i checked there are several things I have to talk about, so this might be a long post, or to be split in several. So let's stop of excuses...

First thing I did was to add the Ruler Component (See previous post) into the Interactions Viewer . The initial step is to define the rules for the component, this has to be in a JSON format. Here the rules defined then:

rules: {
  "location": [ ],
  "action": ["Highlight", "Show", "Hide", "Color" ],
  "target": [ {
   "name": "Proteins",
   "conditions": [ {
    "name": "interactions with",
    "type": "selects",
    "amount": 1,
    "values": [ ]
   }, {
    "name": "number of interactions",
    "type": "numeric_comparison"
   }, {
    "name": "accession number",
    "type": "text_comparison"
   } ]
  }, {
   "name": "Interactions",
   "conditions": [ {
    "name": "protein",
    "type": "selects",
    "amount": 1,
    "values": [ ]
   }, {
    "name": "proteins",
    "type": "selects",
    "amount": 2,
    "values": [ ]
   }, {
    "name": "score",
    "type": "numeric_comparison"
   }, {
    "name": "type of evidence",
    "type": "selects",
    "amount": 1,
    "values": [ 
      "neighborhood",
      "fusion", 
      "cooccurrence", 
      "txt_mining",  
      "microarray",  
      "similarity",  
      "domain",  
      "experimental",  
      "knowledge",  
      "pdb",  
      "interlogs" 
    ]
   }
   ]
  } ]
}

As you might noticed some of the values are empty arrays, those will be populated once a Solr response is obtained. What I'm trying to say is, if a rule requires a set of protein to select from, that field is dynamically filled with the proteins presented in the graphic.

The Ruler component triggers events when a rule is added, removed or re-ordered. Is then the interactions app, who applies the existing rules into the graphic, so all this events are going to call the same function:
self.ruler.onRuleCreated(function( objEvent ) {
 self.manager.widgets["graph"].applyRules();
}); 
self.ruler.onRuleRemoved(function( objEvent ) {
 self.manager.widgets["graph"].applyRules();
}); 
self.ruler.onOrderChanged(function( objEvent ) {
 self.manager.widgets["graph"].applyRules();
}); 

The actions defined in the rules where completely related with displaying options: Show, Hide, Highlight and Color. So my strategy for the applyRules method was to create selectors that operate over the interactions graphic(SVG) to filter the elements that pass certain rule, and then operate the respective action on all of them. The full method is rather long so I wont put the whole thing here (You can check it in the repository), instead here are some important snippets of that code.

The method start by getting the active rules and restarting the graphic to get ride of any previous display changes cause by old rules. Then it loops trough the active rules and built the string selector depending on each case. The only rule evaluated in the following code is Proteins Interacting with a specific protein. The selector is an string containing all the IDs of the nodes that represent proteins interacting with the one selected by the user. This is quite easy because when displaying the graphic, a structure with this info was created: self.graph.interactionsA.



applyRules: function(){
 var self =this;
 var rules = self.manager.widgets["ruler"].ruler.getActiveRules();
 var model = self.manager.widgets["ruler"].rules;
 //Reseting the graph 
 self.graph.vis.selectAll("circle").attr("visibility", 'visible').attr("class", 'node').style("stroke","#fff");
 self.graph.vis.selectAll("line").attr("visibility", 'visible').attr("class", 'link').style("stroke","#999");
 
 var selector ="";
 for (var i=0;i<rules.length;i++){
  selector ="";
  var rule=rules[i];
  if (rule.target==model.target[0].name){ //Proteins
   switch (rule.condition){
    case model.target[0].conditions[0].name: // interactions with
     for (var j=0;j<self.graph.interactionsA[rule.parameters[0]].length;j++){
      selector +="[id =node_"+self.graph.interactionsA[rule.parameters[0]][j].name+"],";
     }
     selector = selector.substring(0, selector.length-1);
     break;



If for example i had 3 proteins in my graphic: p1, p2 and p3. And assuming there are interaction between all of them, a rule like Proteins Interacting with a P1 would generate a selector string like [id =node_p2],[id =node_p3]. All the missing logic in this code deals with the creation of the selector for all the combinations for the defined rules. Some of the generated selectors are explicitly listing the id nodes, such as in this first case, and in other cases the selector uses some wildcards to select several nodes with a simpler string.

Once the selector is created an action is executed with it, so for instance if the action is to highlight, the code self.graph.highlight(selector); is invoked. And that method in the interactions component is defined as:

  highlight: function(selector){
   var self=this;
   self.vis.selectAll(selector).style("stroke", '#3d6');
  },


I decided that actions won't really change the color of the node, but instead the color of the border, this with the purpose of conserving the color that relates a protein with the queried protein.

And all that, to be able to display an interaction like this:

All the nteractions of the proteins O05300 and Q7D8M9, highlighting the proteins interacting with O05300.
You can play with all the rules in the live version of this app at http://biosual.cbio.uct.ac.za/interactions/. And you might notice a lot of other details that I haven't talked here yet, but that's material for a next post. Promise to do it quicker than this time!

Chau Gente!

No comments:

Post a Comment