Commit 9b0059a6 authored by Raphael Müller's avatar Raphael Müller
Browse files

Merge branch 'development' into 'master'

Development

Closes #2, #6, #7, #9, and #8

See merge request !10
parents 5cbb1887 9518a59c
......@@ -14,12 +14,24 @@
</head>
<body>
<div id="app">
<genome-viewer :genome-stats="genome_stats" :feature-data="feature_data"></genome-viewer>
<div id="app" style="position: absolute;left: 25%;right:25%;">
<div style="height:150px">
<genome-viewer :genome-stats="genome_stats" :color-map="{'xRNA':'#CC0000'}":feature-data="feature_data"></genome-viewer>
</div>
<div >
<genome-viewer :genome-stats="genome_stats" :feature-data="feature_data2"></genome-viewer>
</div>
<div style="height:150px">
<genome-viewer :genome-stats="genome_stats" :color-map="genome_stats.colorMap" :feature-data="feature_data2"></genome-viewer>
</div>
<div style="height:150px">
<genome-viewer :genome-stats="genome_stats" :lanes="[-3,-2,-1,1,2,3]" :color-map="{'xRNA':'#CC0000'}":feature-data="feature_data3"></genome-viewer>
</div>
</div>
<script src="js/axis.js"></script>
<script src="js/feature.js"></script>
<script src="js/lane.js"></script>
<script src="js/tool_tip.js"></script>
<script src="js/genome_viewer.js"></script>
<script src="js/app.js"> </script>
</body>
......
......@@ -5,9 +5,20 @@ var app = new Vue({
id: "my-genome",
start: 1706479,
end: 1718084,
tooltip: "name: {name}</br>description: {description}</br>start: {start}</br>end: {end}"
//tooltip: "name: {name}</br>description: {description}</br>start: {start}</br>end: {end}"
tooltip: ["name:Gene Name","type:Gene Type","description","start:Start","end:End","strand:Strand"],
colorMap: {"xRNA":"#CC0000", "PFAM":"#8e44ad"}
},
feature_data: [
{ name: "Gene 1.5",
description: "GMP synthase",
start: 1707479,
end: 1708024,
strand: "+",
zIndex: "4",
type: "ncRNA",
color_border: 'red'
},
{ name: "Gene 1",
description: "GMP synthase",
start: 1706479,
......@@ -22,9 +33,15 @@ var app = new Vue({
start: 1708314,
end: 1708671,
strand: "+",
type: "gene",
color: '#454aff',
color_border: '#000000'
type: "xRNA"
},
{ name: "Gene 2.5",
description: "glyoxalase",
start: 1708414,
end: 1708571,
strand: "+",
zIndeX: "2",
type: "tRNA"
},
{ name: "Gene 3",
description: "ABC transporter ATP-binding protein LlsG",
......@@ -104,6 +121,235 @@ var app = new Vue({
strand: '-',
type: "rRNA"
}
],
feature_data2: [
{ name: "PIWI",
description: "dsRNA guided hydrolysis of ssRNA",
start: 1706879,
end: 1707525,
strand: "+",
zIndex: "12",
type: "PFAM",
shape: "rect",
color_border: 'red'
},
{ name: "Gene 21",
description: "GMP synthase",
start: 1706479,
end: 1708024,
strand: "+",
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 22",
description: "glyoxalase",
start: 1708314,
end: 1708671,
strand: "+",
type: "xRNA",
},
{ name: "Gene 23",
description: "ABC transporter ATP-binding protein LlsG",
start: 1709429,
end: 1710317,
strand: '-',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 24",
description: "ABC transporter permease protein LlsH",
start: 1710316,
end: 1711066,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 25",
description: "LlsX",
start: 1711106,
end: 1711424,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 26",
description: "SagB family dehydrogenase LlsB",
start: 1711420,
end: 1712296,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 27.3",
description: "LlsY",
start: 1712703,
end: 1712821,
zIndex: "10",
strand: '-',
type: "ncRNA",
},
{ name: "Gene 27",
description: "LlsY",
start: 1712503,
end: 1713021,
zIndex: "2",
strand: '-',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 27.6",
description: "LlsY",
start: 1712303,
end: 1713221,
strand: '-',
type: "gene",
},
{ name: "Gene 28",
description: "streptolysin-associated protein LlsD",
start: 1713213,
end: 1714527,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 29",
description: "hypothetical protein",
start: 1715351,
end: 1716125,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 210",
description: "glyoxalase family protein, N-terminal part",
start: 1716189,
end: 1716321,
strand: '+',
type: "gene",
color_border: '#000000'
},
{ name: "Gene 211",
description: "hypothetical protein",
start: 1717235,
end: 1718084,
strand: '-',
type: "rRNA"
}
],
feature_data3: [
{ name: "Gene 21",
description: "GMP synthase",
start: 1706479,
end: 1708024,
strand: "+",
lane: 1,
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 22",
description: "glyoxalase",
start: 1708314,
end: 1708671,
lane: 2,
strand: "+",
type: "xRNA",
},
{ name: "Gene 23",
description: "ABC transporter ATP-binding protein LlsG",
start: 1709429,
end: 1710317,
lane: 3,
strand: '-',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 24",
description: "ABC transporter permease protein LlsH",
start: 1710316,
end: 1711066,
lane: 1,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 25",
description: "LlsX",
start: 1711106,
end: 1711424,
strand: '+',
type: "gene",
lane: 2,
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 26",
description: "SagB family dehydrogenase LlsB",
start: 1711420,
end: 1712296,
lane: 3,
strand: '+',
type: "gene",
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 27",
description: "LlsY",
start: 1712303,
end: 1713221,
strand: '-',
type: "gene",
color: '#454aff',
lane: 1,
color_border: '#000000'
},
{ name: "Gene 28",
description: "streptolysin-associated protein LlsD",
start: 1713213,
end: 1714527,
strand: '+',
type: "gene",
lane: 2,
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 29",
description: "hypothetical protein",
start: 1715351,
end: 1716125,
strand: '+',
type: "gene",
lane: 3,
color: '#454aff',
color_border: '#000000'
},
{ name: "Gene 210",
description: "glyoxalase family protein, N-terminal part",
start: 1716189,
end: 1716321,
lane: 1,
strand: '+',
type: "gene",
color_border: '#000000'
},
{ name: "Gene 211",
description: "hypothetical protein",
start: 1717235,
end: 1718084,
lane: 1,
strand: '-',
type: "rRNA"
}
]
}
})
......
......@@ -2,16 +2,33 @@ Vue.component("feature",{
template:
`
<svg :height="svgHeight" :width="svgWidth" :x="svgX" :y="svgY">
<polygon :points="arrow_coordinates" :style=featureStyle @click="clickEvent" />
<polygon :points="points" :style=featureStyle @click="clickEvent" @mouseover="hoverEvent" @mouseout="$emit('unhover')"/>
</svg>
`,
props: ['svgWidth', 'svgHeight', 'svgX', 'svgY', 'color', 'borderColor', 'featureId'],
props: ['svgWidth', 'svgHeight', 'svgX', 'svgY', 'color', 'borderColor', 'featureId', 'shape','inverse'],
computed: {
featureStyle () {
return {
'fill': this.color,
'stroke': this.borderColor,
'stroke-width': 1
'strokeWidth': 1
}
},
points(){
switch(this.shape){
case "arrow":
if(this.inverse){
return this.arrow_coordinates_inverse
}
else{
return this.arrow_coordinates
}
break;
case "rect":
return this.rect_coordinates
break;
default:
return this.arrow_coordinates
}
},
arrow_coordinates () {
......@@ -26,10 +43,34 @@ Vue.component("feature",{
]
return points.join(' ')
},
arrow_coordinates_inverse () {
let points = [
this.svgWidth + ', ' + this.svgHeight * 0.25,
this.svgWidth + ', ' + this.svgHeight * 0.75,
this.svgWidth * 0.3 + ', ' + this.svgHeight * 0.75,
this.svgWidth * 0.3 + ', ' + this.svgHeight * 0.95,
0 + ', ' + this.svgHeight * 0.5,
this.svgWidth * 0.3 + ', ' + this.svgHeight * 0.05,
this.svgWidth * 0.3 + ', ' + this.svgHeight * 0.25
]
return points.join(' ')
},
rect_coordinates(){
let points = [
this.svgWidth + ', ' + this.svgHeight * 0.25,
'0, ' + this.svgHeight * 0.25,
'0, ' + this.svgHeight * 0.75,
this.svgWidth + ', ' + this.svgHeight * 0.75,
]
return points.join(' ')
}
},
methods: {
clickEvent (evt) {
this.$emit('click', this.featureId)
},
hoverEvent (evt) {
this.$emit('hover', this.featureId)
}
},
data: function(){
......
Vue.component("genome-viewer",{
template: `
<div>
<div style="height:100%;width:100%">
<!--<div class="container-lin-dna">
<div :id="genomeStats.id" class="lin-dna" :data-cluster-start="genomeStats.start" :data-cluster-end="genomeStats.end" style="width: 100%; height: 50px;">
<div v-for="feature in featureData" :key="feature.name" class="region-to-display" :data-region-name="feature.name" :data-region-description="feature.description" :data-region-start="feature.start" :data-region-end="feature.end" :data-region-strand="feature.strand" :data-region-type="feature.type">
......@@ -10,17 +10,25 @@ Vue.component("genome-viewer",{
-->
<svg id="genome-vuer" ref="genomeVuer" height='100%' width='100%'>
<!-- -->
<axis :x="to_w(0)" :y="to_h(0)" :xOffset="10" :vOffset="10" :height="one_height" :width="width" :start="axisStart" :stop="axisStop" :genomeSize="length*100">
<axis :x="to_w(0)" :y="to_h(0)" :vOffset="height/15" :height="one_height" :width="width" :start="axisStart" :stop="axisStop" :genomeSize="length*100">
</axis>
<!-- -->
<lane v-for="lane in lanes" :key="lane.id" :x="to_w(0)" :y="to_h(lane)" :height="2*one_height" :width="to_w(100)">
<lane v-for="lane in lanes" :key="lane.id" :x="to_w(0)" :y="to_h(lane)" :height="2*one_height" :width="to_w(100)" :color="defaultLaneColor">
</lane>
<feature v-for="(feature, index) in featureData" :key="feature.name" :feature-id="feature.name" :svg-width="genomeToPixel(feature.end)-genomeToPixel(feature.start)" :svg-height="one_height" :svg-x="genomeToPixel(feature.start)" :svg-y="to_h(lane(feature.strand))+ one_height/2" :color="getColor(feature)" :border-color="(feature.color_border)?feature.color_border : defaultBorderColor" @click="featureClick">
<feature v-for="(feature, index) in sortedFeatures" :key="feature.name" :feature-id="feature.name" :svg-width="genomeToPixel(feature.end)-genomeToPixel(feature.start)" :svg-height="one_height" :svg-x="genomeToPixel(feature.start)" :svg-y="to_h(lane(feature))+ one_height/2" :color="getColor(feature)" :border-color="(feature.color_border)?feature.color_border : defaultBorderColor" @click="featureClick" @hover="updateFeature" @unhover="currentFeature = undefined" :shape="feature.shape? feature.shape : 'arrow'" :inverse="lane(feature)>0">
</feature>
<!-- -->
</svg>
<tool-tip v-if="currentFeature" :feature="currentFeature" :tip="genomeStats.tooltip" :x="(genomeToPixel(currentFeature.start)+genomeToPixel(currentFeature.end))/2" :y="y+to_h(lane(currentFeature)) + 1.5*one_height " >
</tool-tip>
</div>`,
props: {
lanes: {
default: function(){
return [-1, 1]
}
},
genomeStats: {
validator (value) {
for (let property of ['id', 'start', 'end']) {
......@@ -52,17 +60,23 @@ Vue.component("genome-viewer",{
colorMap: {
default: function(){
return {
'region':'#bdbdbd', // greyLighten
'gene':'#757575', // greyDarken
'cds': '#000000', // black
'rRNA': '#795548', // brown
'tRNA': '#4caf50', // green
'ncRNA': '#ff9800' // orange
}
}
},
defaultLaneColor: {
default: "#FF00BF"
},
},
computed:{
sortedFeatures(){
feats = this.featureData.map(a => ({...a}));
feats.sort((a,b) => {
let azi = (a.zIndex? a.zIndex : "1")
let bzi = (b.zIndex? b.zIndex : "1")
return azi.localeCompare(bzi,undefined,{"numeric": true})
})
return feats
},
stops(){
return this.featureData.map(f => f.end)
},
......@@ -98,6 +112,7 @@ Vue.component("genome-viewer",{
},
mounted() {
var svg_el = this.$refs.genomeVuer.getBoundingClientRect()
this.y = svg_el.y
this.width = svg_el.width
this.height = svg_el.height
//this.height / length([axis and lanes * 2])
......@@ -113,7 +128,24 @@ Vue.component("genome-viewer",{
//this.one_height = this.height/(1 + 2 * this.lanes.length)
},
created(){
window.addEventListener('resize', this.handleResize, false);
},
destroyed(){
window.removeEventListener('resize', this.handleResize)
},
methods:{
shape(feat){
return "arrow"
},
handleResize(){
var svg_el = this.$refs.genomeVuer.getBoundingClientRect()
this.y = svg_el.y
this.width = svg_el.width
this.height = svg_el.height
//#this.width = window.innerWidth;
//#this.height = window.innerHeight;
},
getColor(feature){
if(feature.hasOwnProperty("color")){
return feature.color
......@@ -121,16 +153,24 @@ Vue.component("genome-viewer",{
if(feature.hasOwnProperty("type")){
if(this.colorMap.hasOwnProperty(feature.type)){
return this.colorMap[feature.type]
}else{
return this.defaultColor
}
}else {
return this.defaultColor
else{
if(this.colorMapDefault.hasOwnProperty(feature.type)){
return this.colorMapDefault[feature.type]
}else{
return this.defaultColor
}
}
} else{
return this.defaultColor
}
}
},
lane(str){
return (str=="+")? 1 : -1
lane(feat){
l = feat.lane ? feat.lane : 1
l = l* ((feat.strand=="+")? -1 : +1)
return l
//return (str=="+")? -1 : +1
},
to_h(param){
//param is a value between -n and +n, where n is the number of lanes divided by 2
......@@ -141,7 +181,8 @@ Vue.component("genome-viewer",{
if(param < 0){
return zero + 2 * this.one_height * (param)
}else if(param > 0){
return zero + this.one_height * (param)
return zero + this.one_height + (param-1)*this.one_height*2
//return zero + this.one_height * (param)
}
return zero
},
......@@ -174,12 +215,26 @@ Vue.component("genome-viewer",{
}
console.log( this.fill_in_tooltip_template( feature, this.genomeStats.tooltip ) )
},
updateFeature(feature){
this.currentFeature = this.featureData.find(feat => {
return feat.name == feature;
})
}
},
data: function(){
return {
lanes: [-1, 1],
width: 0,
height: 0
height: 0,
y: 0,
currentFeature: undefined,
colorMapDefault: {
'region':'#bdbdbd', // greyLighten
'gene':'#757575', // greyDarken
'cds': '#000000', // black
'rRNA': '#795548', // brown
'tRNA': '#4caf50', // green
'ncRNA': '#ff9800' // orange
}
}
},
})
......@@ -2,7 +2,7 @@ Vue.component("lane",{
template:
`
<svg :height="height" :x="x" :y="y">
<line :x1="x+10" :y1="height/2" :x2="width" :y2="height/2" stroke="#39FF14" stroke-width="2" stroke-dasharray="20, 5" />
<line :x1="x+10" :y1="height/2" :x2="width" :y2="height/2" :stroke="color" stroke-width="2" stroke-dasharray="20, 5" />
</svg>
`,
props: {
......@@ -26,6 +26,9 @@ Vue.component("lane",{
return true
}
},
color: {
default: '#222222'
},
},
methods: {
my_method(){
......
Vue.component("tool-tip",{
template:
`
<div style="transform:translate(-50%,0%);" :style="tooltipStyle">
<p v-for="property in tipArray" :key='property.id'>
<b>{{tipMap[property]}}:</b> {{feature[property]}}
</p>
<div :style="smallArrorStyle">
</div>
</div>
`,
props: {
x: {
validator (value) {
return true
}
},
y: {
validator (value) {
return true
}
},
width: {
validator (value) {
return true
}
},
tip: {
default: []
},
feature: {
default: {}
}
},
methods: {
fill_in_tooltip_template (feature, template) {
let tooltip = template
//TODO: Iterate over custom properties
for ( let property of ['name', 'description', 'start', 'end', 'strand', 'type'] ){
tooltip = tooltip.replace( "{" + property + "}", feature[property] )
}
return( tooltip )
},
get_tooltip (e){