Commit 68357451 authored by Mikaël Salson's avatar Mikaël Salson
Browse files

Merge branch 'feature-c/conversion_D3V5' into 'dev'

Feature c/conversion d3 v5

See merge request !561
parents 400c513c 10c8211f
Pipeline #117018 passed with stages
in 6 minutes and 26 seconds
......@@ -29,4 +29,6 @@ dep.mk
/browser/cgi/align.cgi
/browser/js/conf.js
node_modules/
cypress/
\ No newline at end of file
cypress/
server/web2py/applications/vidjil/errors
*.bak
......@@ -190,7 +190,7 @@ line {
fill: #000000;
}
.graph_line {
stroke-width: 2.5px;
stroke-width: 1.5px;
cursor: pointer;
stroke: #839496;
}
......@@ -204,7 +204,7 @@ line {
opacity: 0.8;
}
.graph_inactive {
stroke-width: 1.5px;
stroke-width: 0.5px;
cursor: pointer;
display: none;
}
......@@ -247,10 +247,12 @@ line {
#resolution1 {
fill: #000000;
opacity: 1;
pointer-events: none;
}
#resolution5 {
fill: #333333;
fill: #000000;
opacity: 0.6;
pointer-events: none;
}
.graph_time {
fill: #839496;
......
......@@ -190,7 +190,7 @@ line {
fill: #ffffff;
}
.graph_line {
stroke-width: 2.5px;
stroke-width: 1.5px;
cursor: pointer;
stroke: #657b83;
}
......@@ -204,7 +204,7 @@ line {
opacity: 0.8;
}
.graph_inactive {
stroke-width: 1.5px;
stroke-width: 0.5px;
cursor: pointer;
display: none;
}
......@@ -247,10 +247,13 @@ line {
#resolution1 {
fill: #ffffff;
opacity: 1;
pointer-events: none;
}
#resolution5 {
fill: #cccccc;
opacity: 0.6;
pointer-events: none;
}
.graph_time {
fill: #657b83;
......
......@@ -250,7 +250,7 @@ line {
}
.graph_line{
stroke-width : 2.5px;
stroke-width : 1.5px;
cursor:pointer;
stroke: @default;
}
......@@ -267,7 +267,7 @@ line {
}
.graph_inactive{
stroke-width : 1.5px;
stroke-width : 0.5px;
cursor:pointer;
display:none;
}
......@@ -317,11 +317,13 @@ line {
#resolution1{
fill : @background;
opacity : 1;
pointer-events: none;
}
#resolution5{
fill: @border;
fill: @background;
opacity: 0.6;
pointer-events: none;
}
.graph_time{
......
......@@ -4,13 +4,14 @@ requirejs.config({
baseUrl: 'js/lib',
paths: {
app: '',
jquery: 'jquery-3.3.1.min'
jquery: 'jquery-3.3.1.min',
d3: 'd3.v5.min',
}
});
// Load required libraries first
require(['d3'], function(d3) {window.d3 = d3;});
require(["jquery",
"d3.v3",
"jquery.form",
"file",
"tsne",
......
......@@ -107,6 +107,8 @@ function Graph(id, model, database) {
this.m.graph = this // TODO: find a better way to do this
this.db = database;
this.lineGenerator = d3.line().curve(d3.curveMonotoneX);
}
Graph.prototype = {
......@@ -192,9 +194,6 @@ Graph.prototype = {
this.axis_container = d3.select("#" + this.id + "_clipped")
.append("svg:g")
.attr("id", "axis_container")
this.reso_container = d3.select("#" + this.id + "_clipped")
.append("svg:g")
.attr("id", "reso_container")
this.data_container = d3.select("#" + this.id + "_clipped")
.append("svg:g")
.attr("id", "data_container")
......@@ -207,6 +206,9 @@ Graph.prototype = {
this.text_container = d3.select("#" + this.id + "_clipped")
.append("svg:g")
.attr("id", "text_container")
this.reso_container = d3.select("#" + this.id + "_clipped")
.append("svg:g")
.attr("id", "reso_container")
this.build_menu()
.build_list();
......@@ -332,22 +334,22 @@ Graph.prototype = {
* */
update : function (speed) {
speed = typeof speed !== 'undefined' ? speed : 500;
this.g_clone = this.clones_container.selectAll("path")
.data(this.data_clone);
this.initAxis()
.initData()
.updateRes()
.updateClones()
.draw(speed);
.drawAxis(speed)
.drawData(speed)
.drawRes(speed)
},
/* update resolution curves
*
* */
updateRes : function () {
if(this.mode != "stack"){
this.data_res[0].path = this.constructPathR(1);
this.data_res[1].path = this.constructPathR(5);
}
this.initRes();
return this
},
......@@ -530,6 +532,8 @@ Graph.prototype = {
var res = []
for (var i = 0; i < this.m.samples.number; i++) {
res[i] = (r / this.m.reads.segmented[i])
if(this.m.reads.segmented[i]==0) res[i] = 1;
if(res[i] > this.displayMax) res[i] = this.displayMax;
}
if (typeof res !== "undefined" && res.length !== 0) {
......@@ -551,16 +555,15 @@ Graph.prototype = {
p.push([1, (1 - this.scale_x(size[this.m.samples.order[this.graph_col.length - 1]] * this.m.precision))]);
p.push([1, 1 + 0.1]);
var x = (p[0][0] * this.resizeW + this.marge4)
var y = (p[0][1] * this.resizeH + this.marge5)
var che = ' M ' + x + ',' + y;
for (var m = 1; m < p.length; m++) {
var tab = []
for (var m = 0; m < p.length; m++) {
x = (p[m][0] * this.resizeW + this.marge4)
y = (p[m][1] * this.resizeH + this.marge5)
che += ' L ' + x + ',' + y;
if (isNaN(x)) return ' M 0,' + this.resizeH;
if (isNaN(y)) return ' M 0,' + this.resizeH;
tab.push([x.toFixed(3),y.toFixed(3)]);
}
che += ' Z ';
return che;
return this.lineGenerator(tab);
} else return "";
}, //fin constructPathR()
......@@ -574,10 +577,14 @@ Graph.prototype = {
t = 0;
var p;
var clone = self.m.clone(id)
if (!clone.isActive() && !clone.isSelected() && !clone.isFocus()) return ' M 0,' + self.resizeH;
if (clone.top > self.display_limit)return ' M 0,' + self.resizeH;
var size = []
for (var i = 0; i < this.graph_col.length; i++) {
if (seq_size) size[i] = this.m.clone(id).getSequenceSize(this.m.samples.order[i])
else size[i] = this.m.clone(id).getSize(this.m.samples.order[i])
else size[i] = this.m.clone(id).getSize(this.m.samples.order[i])
}
var x = this.graph_col[0];
......@@ -588,14 +595,11 @@ Graph.prototype = {
if (size[0] === 0) {
p = [];
} else {
p = [
[(x + (Math.random() * 0.05) - 0.125), (1 - y)]
];
p.push([(x + (Math.random() * 0.05) + 0.075), (1 - y)]);
p = [ [(x + (Math.random() * 0.05) - 0.125), (1 - y)],
[(x + (Math.random() * 0.05) + 0.075), (1 - y)]];
}
}
//plusieurs points de suivi
else {
......@@ -606,14 +610,10 @@ Graph.prototype = {
if (size[0] === 0) {
p = [];
} else {
p = [
[(x - 0.03), (1 - y)]
];
p.push([(x), (1 - y)]);
p = [ [(x - 0.03), (1 - y)],
[(x), (1 - y)] ];
if (to == size[0]) {
p.push([(x + 0.03), (1 - y)]);
}
if (to == size[0]) p.push([(x + 0.03), (1 - y)]);
}
//points suivants
......@@ -626,40 +626,30 @@ Graph.prototype = {
y = this.scale_x(size[k] * this.m.precision)
if (size[k] === 0) {
if (p.length !== 0) {
p.push([(x), (1 + 0.03)]);
}
if (p.length !== 0) p.push([(x), (1 + 0.03)]);
} else {
//si premiere apparition du clone sur le graphique
if (p.length === 0) {
p.push([(x - 0.03), (1 - y)]);
}
if (p.length === 0) p.push([(x - 0.03), (1 - y)]);
p.push([(x), (1 - y)]);
//si derniere apparition du clone sur le graphique
if (to == size[k]) {
p.push([(x + 0.03), (1 - y)]);
}
if (to == size[k]) p.push([(x + 0.03), (1 - y)]);
}
}
}
}
var tab = []
if (p.length !== 0){
x = (p[0][0] * self.resizeW + self.marge4)
y = (p[0][1] * self.resizeH + self.marge5)
var che = ' M ' + x + ',' + y;
for (var m = 1; m < p.length; m++) {
for (var m = 0; m < p.length; m++) {
x = (p[m][0] * self.resizeW + self.marge4)
y = (p[m][1] * self.resizeH + self.marge5)
che += ' L ' + x + ',' + y;
if (isNaN(x)) return ' M 0,' + self.resizeH;
if (isNaN(y)) return ' M 0,' + self.resizeH;
tab.push([x.toFixed(3),y.toFixed(3)]);
}
return che;
return this.lineGenerator(tab);
}else{
return ' M 0,' + self.resizeH;
}
......@@ -718,7 +708,6 @@ Graph.prototype = {
.initData()
.initClones()
.initRes()
.build_path_events()
return this
},
......@@ -787,6 +776,9 @@ Graph.prototype = {
.attr("id", function (d) {
return "poly" + d.name;
})
.attr("d", function (p) {
return p.path
})
this.g_clone.exit()
.remove();
......@@ -814,19 +806,18 @@ Graph.prototype = {
path: this.constructPathR(5)
});
this.g_res = this.reso_container.selectAll("g")
this.g_res = this.reso_container.selectAll("path")
.data(this.data_res);
this.g_res.enter()
.append("svg:g")
.append("svg:path")
.attr("id", function (d) {
return d.name;
})
.attr("d", function (p) {
return p.path
});
this.g_res.exit()
.remove();
this.g_res.append("path")
this.g_res.exit()
.remove();
return this
},
......@@ -959,19 +950,10 @@ Graph.prototype = {
*
* */
initOrdinateClones : function () {
this.m.update_precision()
var max = this.m.precision*this.m.max_size
//get ready for something really dirty
for (var i=0; i<this.m.samples.order.length; i++) {
for (var j=0; j<this.m.clones.length; j++){
if (this.m.clone(j).hasSizeConstant()) {
var size = this.m.precision*this.m.clone(j).getSize()
if (size>max) max=size;
}
}
}
this.scale_x = d3.scale.log()
this.scale_x = d3.scaleLog()
.domain([1, max])
.range([0, 1]);
......@@ -986,19 +968,28 @@ Graph.prototype = {
this.data_axis.push({"type" : "axis_h", "class" : "graph_text", "text" : "50%" ,"orientation" : "hori", "pos" : 0.5});
this.data_axis.push({"type" : "axis_h", "class" : "graph_text", "text" : "100%" ,"orientation" : "hori", "pos" : 0});
}else{
var height = 1;
while(height<this.m.max_size) height = height*10
while ((height * this.m.precision) > 0.5) {
//increase the max value displayable in graph until we can display the current biggest clone
this.displayMax = 0.00001;
while(this.displayMax<this.m.max_size) this.displayMax = this.displayMax*10
//update scale
this.scale_x = d3.scaleLog()
.domain([1, this.m.precision*this.displayMax])
.range([0, 1]);
//compute axis label
var axis_value = this.displayMax
while ((axis_value * this.m.precision) > 0.5) {
var d = {};
d.type = "axis_h";
d.text = this.m.formatSize(height, false)
d.text = this.m.formatSize(axis_value, false)
d['class'] = "graph_text";
d.orientation = "hori";
d.pos = 1 - this.scale_x(height * this.m.precision);
d.pos = 1 - this.scale_x(axis_value * this.m.precision);
if (d.pos>=-0.1) this.data_axis.push(d);
height = height / 10;
axis_value = axis_value/10;
}
}
......@@ -1037,12 +1028,12 @@ Graph.prototype = {
//choose the best scale (linear/log) depending of the space between min/max
if ( g_min!==0 && (g_min*100)<g_max){
this.scale_data = d3.scale.log()
this.scale_data = d3.scaleLog()
.domain([g_max, g_min])
.range([0, 1]);
}else{
if ( (g_min*2)<g_max) g_min = 0
this.scale_data = d3.scale.linear()
this.scale_data = d3.scaleLinear()
.domain([g_max, g_min])
.range([0, 1]);
}
......@@ -1223,27 +1214,36 @@ Graph.prototype = {
if (this.mode=="stack"){
//volumes
this.g_clone
var clone = this.g_clone;
if (speed !== 0){
clone = clone
.transition()
.duration(speed)
}
clone
.style("fill", function (d) {
return self.m.clone(d.id).getColor();
})
.style("stroke", "none")
.attr("class", function (p) {
var clone = self.m.clone(p.id)
if (!clone.isActive()) return "graph_inactive";
if (clone.isSelected()) return "graph_select";
if (clone.isFocus()) return "graph_focus";
if (!clone.isActive()) return "graph_inactive";
c++
return "graph_line";
})
.attr("id", function (d) {
return "poly" + d.name;
})
.attr("d", function (d) {
return d.path
})
}else{
//courbes
selected_clones = this.g_clone;
if (typeof list != "undefined"){
selected_clones = this.g_clone.filter(function(d, i) {
selected_clones = this.g_clone.filter(function(d) {
if (list.indexOf(d.id) != -1) return true;
return false
});
......@@ -1267,36 +1267,20 @@ Graph.prototype = {
.attr("id", function (d) {
return "poly" + d.name;
})
}
var clone = this.g_clone
if (speed !== 0){
clone = clone
.transition()
.duration(speed)
.on("mouseover", function (d) {
self.m.focusIn(d.id);
})
.on("click", function (d) {
self.clickGraph(d.id);
})
.attr("d", function (d) {
return d.path
});
}
clone.attr("d", function (p) {
return p.path
})
return this
},
build_path_events : function (){
var self = this;
this.clones_container.selectAll("path")
.on("mouseover", function (d) {
self.m.focusIn(d.id);
})
.on("click", function (d) {
self.clickGraph(d.id);
});
return this;
},
/* renderer function for data curves
*
* */
......@@ -1355,14 +1339,11 @@ Graph.prototype = {
drawRes: function (speed) {
var self = this;
var res = this.g_res.selectAll("path")
if (speed !== 0){
res = res
.transition()
.duration(speed)
}
res.attr("d", function (p) {
var res = this.g_res
res
.transition()
.duration(500)
.attr("d", function (p) {
return p.path
})
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -748,7 +748,7 @@ changeAlleleNotation: function(alleleNotation) {
clone.normalized_reads[time] != null &&
raw == undefined) {
return clone.normalized_reads[time] ;
} else if (clone.hasSizeDistrib()){
} else if (clone.hasSizeDistrib() && !isNaN(clone.current_reads[time])){
return clone.current_reads[time]
} else {
return clone.reads[time] ;
......@@ -820,34 +820,30 @@ changeAlleleNotation: function(alleleNotation) {
* compute min/max clones sizes and abundance color scale<br>
* clone size can change depending the parameter so it's neccesary to recompute precision from time to time
* */
update_precision: function () {
var min_size = 1
var max
update_precision: function () {
this.min_size = 1
this.max_size = 0
for (var i=0; i<this.samples.order.length; i++){
var t = this.samples.order[i]
var size = this.min_sizes[t]
size = this.normalize(this.min_sizes[t], t)
if (size < min_size) min_size = size
if (size < this.min_size) this.min_size = size
}
this.max_size = 1
this.min_size = min_size
if (this.normalization_mode != this.NORM_FALSE){
for (var j=0; j<this.samples.order.length; j++){
if(this.normalization.size_list[j]==0){
max = this.normalization.expected_size
}else{
max = this.normalization.expected_size/this.normalization.size_list[j]
}
if (max>this.max_size) this.max_size=max;
for (var j=0;j<this.clones.length;j++){
if (this.clone(j).isActive()) {
max_s = this.clones[j].getMaxSize()
if (max_s > this.max_size)
this.max_size = max_s
}
}
}
//*2 pour avoir une marge minimum d'un demi-log
// 1/0 == infinity
this.precision=(1/this.min_size)*2
this.scale_color = d3.scale.log()
this.scale_color = d3.scaleLog()
.domain([1, this.precision])
.range([250, 0]);
},
......@@ -1301,13 +1297,14 @@ changeAlleleNotation: function(alleleNotation) {
* display an icon in the top-container if a view has not finished an update
*/
updateIcon:function(){
var div = document.getElementById("updateIcon");
if (div==null) return
if (typeof (this.divUpdateIcon) == "undefined")
this.divUpdateIcon = document.getElementById("updateIcon");
if (this.divUpdateIcon==null) return