Last active
April 5, 2018 13:37
-
-
Save nimezhu/adb646c9ef87fdb1084b1d0876a8133d to your computer and use it in GitHub Desktop.
Nucleome Browser Plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Nucleome Browser Plugin | |
// @namespace http://genome.compbio.cs.cmu.edu:8080 | |
// @version 0.0.4 | |
// @description link nucleme browser with other genome browsers such as UCSC Genome Browser and WASHU Genome Browser. Works with NBrowser 'Browser Manager' Panel. | |
// @author xiaopeng.zhu([email protected]) | |
// @include http://genome.ucsc.edu/cgi-bin/hgTracks* | |
// @include http://epigenomegateway.wustl.edu/browser/* | |
// @grant none | |
// @require https://d3js.org/d3.v5.min.js | |
// @updateURL https://gist.github.com/nimezhu/adb646c9ef87fdb1084b1d0876a8133d/raw/d2418ccc7bbcfe475274fd2c8b159a4d790f111e/cnb.user.js | |
// @downloadURL https://gist.github.com/nimezhu/adb646c9ef87fdb1084b1d0876a8133d/raw/d2418ccc7bbcfe475274fd2c8b159a4d790f111e/cnb.user.js | |
// ==/UserScript== | |
// == USER CONFIG == | |
var src = "http://genome.compbio.cs.cmu.edu:8080"; | |
//var src = "http://x7.andrew.cmu.edu:8080"; //dev server | |
var firstRegionToText = function(d) { | |
return d[0].chr+":"+d[0].start+"-"+d[0].end; | |
}; | |
var regionText = function(d) { | |
return d.chr + ":" + d.start + "-" + d.end; | |
}; | |
var regionsText = function(regions) { | |
var r = []; | |
regions.forEach(function(d) { | |
r.push(regionText(d)); | |
}); | |
return r.join(","); | |
}; | |
var parseRegion = function(s){ | |
var a = s.split(":"); | |
if (a.length==1) { | |
return { | |
"chr": a[0], | |
"start": 0, | |
"end" : undefined | |
}; | |
} | |
var x = a[1].split("-"); | |
return { | |
"chr": a[0], | |
"start": +x[0], | |
"end": +x[1] | |
}; | |
}; | |
var watch = function(target, prop, handler) { | |
if (target.__lookupGetter__(prop) != null) { | |
return true; | |
} | |
var oldval = target[prop], | |
newval = oldval, | |
self = this, | |
getter = function () { | |
return newval; | |
}, | |
setter = function (val) { | |
if (Object.prototype.toString.call(val) === '[object Array]') { | |
val = _extendArray(val, handler, self); | |
} | |
oldval = newval; | |
newval = val; | |
handler.call(target, prop, oldval, val); | |
}; | |
if (delete target[prop]) { // can't watch constants | |
if (Object.defineProperty) { // ECMAScript 5 | |
Object.defineProperty(target, prop, { | |
get: getter, | |
set: setter, | |
enumerable: false, | |
configurable: true | |
}); | |
} else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy | |
Object.prototype.__defineGetter__.call(target, prop, getter); | |
Object.prototype.__defineSetter__.call(target, prop, setter); | |
} | |
} | |
return this; | |
}; | |
var unwatch = function(target, prop) { | |
var val = target[prop]; | |
delete target[prop]; // remove accessors | |
target[prop] = val; | |
return this; | |
}; | |
var _extendArray = function(arr, callback, framework) { | |
if (arr.__wasExtended === true) return; | |
function generateOverloadedFunction(target, methodName, self) { | |
return function () { | |
var oldValue = Array.prototype.concat.apply(target); | |
var newValue = Array.prototype[methodName].apply(target, arguments); | |
target.updated(oldValue, motive); | |
return newValue; | |
}; | |
} | |
arr.updated = function (oldValue, self) { | |
callback.call(this, 'items', oldValue, this, motive); | |
}; | |
arr.concat = generateOverloadedFunction(arr, 'concat', motive); | |
arr.join = generateOverloadedFunction(arr, 'join', motive); | |
arr.pop = generateOverloadedFunction(arr, 'pop', motive); | |
arr.push = generateOverloadedFunction(arr, 'push', motive); | |
arr.reverse = generateOverloadedFunction(arr, 'reverse', motive); | |
arr.shift = generateOverloadedFunction(arr, 'shift', motive); | |
arr.slice = generateOverloadedFunction(arr, 'slice', motive); | |
arr.sort = generateOverloadedFunction(arr, 'sort', motive); | |
arr.splice = generateOverloadedFunction(arr, 'splice', motive); | |
arr.unshift = generateOverloadedFunction(arr, 'unshift', motive); | |
arr.__wasExtended = true; | |
return arr; | |
}; | |
var ucscPlugin = function() { | |
'use strict'; | |
var scale; | |
function addDiv() { | |
var pos = $("#imgTbl").position(); | |
var width = $("#imgTbl").width(); | |
var height = $("#imgTbl").height(); | |
console.log("addDiv",pos,width,height); | |
var respdiv = d3.select("body") | |
.selectAll(".scope") | |
.data([0]); | |
respdiv.exit().remove(); | |
respdiv.enter() | |
.append("div") | |
.classed("scope",true) | |
.attr("id","scope"); | |
//.merge(respdiv) | |
respdiv.style("position","absolute") | |
.style("top",pos.top+"px") | |
.style("left",pos.left+"px") | |
.style("height",height+"px") | |
.style("width",width+"px") | |
.style("background-color","#FFF") | |
.style("opacity",0.1); | |
respdiv.selectAll(".brush").remove(); | |
d3.select("#imgTbl").on("mouseover",function(){ | |
respdiv.style("display","none"); | |
}) | |
.on("mouseout",function(){ | |
respdiv.style("display",null); | |
}); | |
} | |
var respdiv; | |
function onBrush(r){ | |
var height = $("#imgTbl").height(); | |
var pos = $("#imgTbl").position(); | |
respdiv = d3.select("body") | |
.select("#scope"); | |
respdiv.style("position","absolute") | |
.style("top",pos.top+"px") | |
.style("left",pos.left+"px") | |
.style("height",height+"px"); | |
var r0 = respdiv.selectAll(".brush").data(r); | |
r0.exit().remove(); | |
r0.enter().append("div") | |
.classed("brush",true) | |
.style("position","absolute") | |
.style("top","0px") | |
.style("background-color","#000") | |
.style("opacity",0.1) | |
.merge(r0) | |
.style("height",height+"px") | |
.style("left",function(d){return scale(d.start)+"px";}) | |
.style("width",function(d){return (scale(d.end)-scale(d.start))+"px";}); | |
} | |
var lastSent; | |
var recieve; | |
function onUpdate(d){ | |
console.log("UPDATE???",d); | |
var r = d; | |
var txt = firstRegionToText(r); | |
recieve = txt; | |
var p=document.getElementById('positionInput'); | |
p.value=txt; | |
var pNow = document.getElementById('position'); | |
console.log('now',pNow.value,'old',p.value); | |
if(pNow.value!=p.value){ | |
pNow.value=p.value; | |
var jump=document.getElementById('hgt.jump').click(); | |
scale.domain([r[0].start,r[0].end]); | |
d3.select("body").select("#scope").selectAll(".brush").remove(); | |
} | |
} | |
var lastRegion = ""; | |
var _callback = function(){ | |
var db = document.getElementsByName("db"); | |
if (genomePos.original != undefined && genomePos.original != lastSent && genomePos.original!=recieve) { | |
var d0 = parseRegion(genomePos.original); | |
d0.genome = db[0].getAttribute("value"); | |
console.log("D0",d0); | |
window.opener.postMessage({code:'update',data:d0},src); | |
scale.domain([d0.start,d0.end]); | |
lastSent = genomePos.original; | |
} | |
}; | |
var onNav = function(d){ | |
if(window.opener) { | |
_callback(); | |
} | |
}; | |
setTimeout(watch(genomePos,"original",onNav),200); | |
(function() { | |
var position = $("#imgTbl").position(); | |
var width = $("#imgTbl").width(); | |
scale = d3.scaleLinear(); | |
scale.range([123,width]); | |
var d0 = parseRegion(genomePos.original); | |
scale.domain([d0.start,d0.end]); | |
addDiv(); | |
onNav(); | |
})(); | |
window.addEventListener("message",function(d){ | |
if (d.origin == src) { | |
if (d.data.code=="update"){ | |
console.log("update",d.data.data); | |
onUpdate(d.data.data); | |
} | |
if (d.data.code=="brush"){ | |
onBrush(d.data.data); | |
} | |
} | |
},false); | |
}; | |
var washuPlugin = function() { | |
'use strict'; | |
var receive; | |
var axis; | |
var svg; | |
var scale = d3.scaleLinear(); | |
var processing = true; | |
window.loading_done = function(){ | |
waitcloak.style.display = 'none'; | |
var r = $(".header_b").first().text(); | |
var d = parseRegion(r); | |
if (window.opener && !processing){ | |
window.opener.postMessage({code:"update",data:d},src); | |
} | |
axis = d3.select("#sukn_main").select("table").select("tbody").select("tr:nth-child(3)").select("td:nth-child(2)").select("div"); | |
axis.selectAll("svg").remove(); | |
var width = axis.style("width").replace("px",""); | |
svg = axis.append("svg").attr("width",width).attr("height",10); | |
scale.range([0,width]); | |
scale.domain([d.start,d.end]); | |
processing = false; //processed response. | |
console.log("processed",processing); | |
}; | |
var lastRegion = ""; | |
window.addEventListener("message",function(d){ | |
if (d.origin == src) { | |
if (d.data.code=="update"){ | |
console.log("update",d.data.data); | |
var el = $("#menu > div > div > table > tbody")[2]; | |
var newRegion = regionText(d.data.data[0]); | |
if (lastRegion != newRegion) { | |
lastRegion = newRegion; | |
receive = newRegion; | |
processing = true; | |
$(el).find("input").first().val(regionText(d.data.data[0])); | |
$(".header_b").first().click(); | |
$(el).find("button").first().click(); | |
} | |
} | |
if (d.data.code=="brush"){ | |
var rects = svg.selectAll("rect").data(d.data.data); | |
rects.exit().remove(); | |
rects.enter().append("rect") | |
.merge(rects) | |
.attr("x",function(d){return scale(d.start);}) | |
.attr("width",function(d){return scale(d.end)-scale(d.start);}) | |
.attr("y",0) | |
.attr("height",10) | |
.attr("opacity",0.2); | |
} | |
} | |
},false); | |
}; | |
window.addEventListener('load', function() { | |
var key = window.location.origin; | |
if (key == "http://epigenomegateway.wustl.edu") { | |
console.log("using washu plugin"); | |
washuPlugin(); | |
} else if (key == "http://genome.ucsc.edu") { | |
ucscPlugin(); | |
} | |
},false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment