Commit 764d76e3 authored by flothoni's avatar flothoni

Merge branch 'dev' of https://gitlab.inria.fr/vidjil/vidjil into feature-t/fuse_export_as_airr

parents 00cb9d18 b7362fd0
Pipeline #130021 passed with stage
in 8 seconds
......@@ -55,6 +55,7 @@ test_germlines:
include:
- local: '/doc/.gitlab-ci.yml'
- local: 'algo/.gitlab-ci-compilers.yml' # Stage multiple_tests
# Algorithm
......@@ -177,33 +178,6 @@ deploy_release_prod:
make -C vidjil-algo-${release_name};\
ln -sfT vidjil-algo-${release_name} next"
.testing-compilers: &test_various_compilers
stage: multiple_tests
tags:
- several-compilers
script:
- |
for CXX in $COMPILERS; do
echo "**** Using $CXX for compilation ****"
make -C algo clean
make -C algo CXX=$CXX unit
make -C algo CXX=$CXX should
make -C algo CXX=$CXX valgrind_unit
done
test_various_compilers_manual:
<<: *test_various_compilers
when: manual
only:
- /^feature-.*a.*\/.*$/
- schedules
test_various_compilers_release:
<<: *test_various_compilers
only:
- /^feature-.*a.*\/release$/
# Client
test_browser_unit:
......
.testing-compilers:
stage: multiple_tests
tags:
- cidocker
before_script:
- apt-get update
- apt-get install -y time valgrind python3 wget tar
script:
- $CXX --version
- make demo data germline
- make -C algo clean
- make -C algo CXX=$CXX CC=$CC unit
- make -C algo CXX=$CXX CC=$CC should
- make -C algo CXX=$CXX CC=$CC valgrind_unit
.installing-compiler:
before_script:
- apt-get update
- apt-get install -y time valgrind python3 $COMPILER_PKG-$VERSION zlib1g-dev make wget tar python2.7
- ln -sf /usr/bin/python2.7 /usr/bin/python
- export CXX=${COMPILER_CPP}-$VERSION
- export CC=${COMPILER_C}-$VERSION
.testing-gcc:
extends: .testing-compilers
variables:
CXX: g++
CC: gcc
.testing-clang:
variables:
COMPILER_PKG: "clang"
COMPILER_CPP: "clang++"
COMPILER_C: "clang"
VERSION: $CLANG_VERSION
extends:
- .testing-compilers
- .installing-compiler # Overrides the before_script to install the compiler
.installing-testing-gcc:
variables:
COMPILER_PKG: "g++"
COMPILER_CPP: "g++"
COMPILER_C: "gcc"
VERSION: $GCC_VERSION
extends:
- .testing-compilers
- .installing-compiler
.testing_various_compilers_manual:
when: manual
only:
- /^feature-.*a.*\/.*$/
- schedules
.testing_various_compilers_release:
only:
- /^feature-.*a.*\/release$/
test_gcc48_manual:
image: debian:8-slim
variables:
GCC_VERSION: "4.8"
extends:
- .installing-testing-gcc
- .testing_various_compilers_manual
test_gcc48_release:
image: debian:8-slim
variables:
GCC_VERSION: "4.8"
extends:
- .installing-testing-gcc
- .testing_various_compilers_release
test_gcc5_manual:
image: gcc:5.3
extends:
- .testing-gcc
- .testing_various_compilers_manual
test_gcc5_release:
image: gcc:5.3
extends:
- .testing-gcc
- .testing_various_compilers_release
test_gcc6_manual:
image: gcc:6.3
extends:
- .testing-gcc
- .testing_various_compilers_manual
test_gcc6_release:
image: gcc:6.3
extends:
- .testing-gcc
- .testing_various_compilers_release
test_gcc7_manual:
image: gcc:7.3
extends:
- .testing-gcc
- .testing_various_compilers_manual
test_gcc7_release:
image: gcc:7.3
extends:
- .testing-gcc
- .testing_various_compilers_release
test_gcc8_manual:
image: gcc:8
extends:
- .testing-gcc
- .testing_various_compilers_manual
test_gcc8_release:
image: gcc:8
extends:
- .testing-gcc
- .testing_various_compilers_release
test_gcc9_manual:
image: gcc:9
extends:
- .testing-gcc
- .testing_various_compilers_manual
test_gcc9_release:
image: gcc:9
extends:
- .testing-gcc
- .testing_various_compilers_release
test_clang34_manual:
image: debian:8-slim
variables:
CLANG_VERSION: "3.4"
extends:
- .testing-clang
- .testing_various_compilers_manual
test_clang34_release:
image: debian:8-slim
variables:
CLANG_VERSION: "3.4"
extends:
- .testing-clang
- .testing_various_compilers_release
test_clang4_manual:
image: debian:8-slim
variables:
CLANG_VERSION: "4.0"
extends:
- .testing-clang
- .testing_various_compilers_manual
test_clang4_release:
image: debian:8-slim
variables:
CLANG_VERSION: "4.0"
extends:
- .testing-clang
- .testing_various_compilers_release
test_clang6_manual:
image: debian:8-slim
variables:
CLANG_VERSION: "6.0"
extends:
- .testing-clang
- .testing_various_compilers_manual
test_clang6_release:
image: debian:8-slim
variables:
CLANG_VERSION: "6.0"
extends:
- .testing-clang
- .testing_various_compilers_release
test_clang7_manual:
image: debian:10-slim
variables:
CLANG_VERSION: "7"
extends:
- .testing-clang
- .testing_various_compilers_manual
test_clang7_release:
image: debian:10-slim
variables:
CLANG_VERSION: "7"
extends:
- .testing-clang
- .testing_various_compilers_release
......@@ -6,7 +6,7 @@ $ All sequences have been seen as unique clone
$ All sequences have been seen as different IKZF1 recombinations
1: IKZF1 .* 22
### control sequence given by Debré ###
### control sequence given by Debre ###
# del4-7__jonction_intron3_intron7
$ Find the correct assignation for the sequence IKZF1-INTRON-3//IKZF1-INTRON-7
1: IKZF1-INTRON-3 16/CCCGCG/8 IKZF1-INTRON-7
......@@ -38,9 +38,9 @@ $ Find the correct assignation for the sequence
### 13922 - sequences ikfz1 ####
$ Find the correct assignation for the sequence (témoin del4-7)
$ Find the correct assignation for the sequence (temoin del4-7)
1: IKZF1-INTRON-3 1//2 IKZF1-INTRON-7
$ Find the correct assignation for the sequence (témoin del2-7)
$ Find the correct assignation for the sequence (temoin del2-7)
1: IKZF1-INTRON-1 8/CCCTTC/3 IKZF1-INTRON-7
$ Find the correct assignation for the sequence (seq 4-7 du patient)
1: IKZF1-INTRON-3 0/TCGG/6 IKZF1-INTRON-7
......
......@@ -250,8 +250,9 @@ void testGetMaximum() {
// ^^^^^^^^^^
vector<KmerAffect> affectations(a, a+sizeof(a)/sizeof(KmerAffect));
KmerAffectAnalyser kaa(*index, "", affectations);
TAP_TEST_EQUAL(kaa.getSequence(), "", TEST_AA_GET_SEQUENCE, "");
string seq = "AAAAAAAAAAAAAA";
KmerAffectAnalyser kaa(*index, seq, affectations);
TAP_TEST_EQUAL(kaa.getSequence(), seq, TEST_AA_GET_SEQUENCE, "");
affect_infos results = kaa.getMaximum(AFFECT_J_BWD, AFFECT_V_BWD, 2., 0);
TAP_TEST(! results.max_found, TEST_AA_GET_MAXIMUM_MAX_FOUND,
......@@ -288,7 +289,8 @@ void testGetMaximum() {
// V V V V V V V V V V J J J V V V
// ^^^^^^^^^^^^
vector<KmerAffect> affectations2(a2, a2+sizeof(a2)/sizeof(KmerAffect));
KmerAffectAnalyser kaa2(*index, "", affectations2);
seq = "AAAAAAAAAAAAAAAA";
KmerAffectAnalyser kaa2(*index, seq, affectations2);
results = kaa2.getMaximum(AFFECT_V, AFFECT_J, 2., 0);
TAP_TEST(! results.max_found,
TEST_AA_GET_MAXIMUM_MAX_FOUND, "(" << results.first_pos_max
......@@ -332,7 +334,8 @@ void testGetMaximum() {
// V V V V V V J J J // nb_before_left (6), nb_after_right (3)
// V // nb_before_right (1)
vector<KmerAffect> affectations3(a3, a3+sizeof(a3)/sizeof(KmerAffect));
KmerAffectAnalyser kaa3(*index, "", affectations3);
seq = "AAAAAAAAAAAAAAAAAAAAA";
KmerAffectAnalyser kaa3(*index, seq, affectations3);
// span = 4, maxOverlap = 0
results = kaa3.getMaximum(AFFECT_V, AFFECT_J, 2., 0);
......@@ -363,7 +366,7 @@ void testGetMaximum() {
// ^^^^^^^^^
// V V V V V V J J J J J J // nb_before_left (6), nb_after_right (6)
vector<KmerAffect> affectations4(a4, a4+sizeof(a4)/sizeof(KmerAffect));
KmerAffectAnalyser kaa4(*index, "", affectations4);
KmerAffectAnalyser kaa4(*index, seq, affectations4);
// span = 4, maxOverlap = 0
results = kaa4.getMaximum(AFFECT_V, AFFECT_J, 2., 0);
......@@ -396,7 +399,7 @@ void testGetMaximum() {
// J J J // nb_after_left (3)
vector<KmerAffect> affectations5(a5, a5+sizeof(a5)/sizeof(KmerAffect));
KmerAffectAnalyser kaa5(*index, "", affectations5);
KmerAffectAnalyser kaa5(*index, seq, affectations5);
results = kaa5.getMaximum(AFFECT_V, AFFECT_J, 2., 0);
TAP_TEST(! results.max_found, TEST_AA_GET_MAXIMUM_MAX_FOUND,
......@@ -425,7 +428,7 @@ void testGetMaximum() {
// J-J-J-J-J-J-J-J-V-V-V-V-V-J-J-J-V-V-V-V-
// ^^^^^^^^^^
vector<KmerAffect> affectations6(a6, a6+sizeof(a6)/sizeof(KmerAffect));
KmerAffectAnalyser kaa6(*index, "", affectations6);
KmerAffectAnalyser kaa6(*index, seq, affectations6);
results = kaa6.getMaximum(AFFECT_J_BWD, AFFECT_V_BWD, 2., 0);
TAP_TEST(! results.max_found, TEST_AA_GET_MAXIMUM_MAX_FOUND,
......
......@@ -576,7 +576,7 @@ line {
font-weight: bold;
}
.list_sort {
margin-right: 30px;
margin-right: 20px;
float: right;
}
/*style segmenter element*/
......@@ -1501,7 +1501,7 @@ h3 .uid {
#db_table_container {
overflow-y: scroll;
overflow-x: hidden;
height: calc(100% -30px);
height: calc(100% - 30px);
position: relative;
}
#db_fixed_header {
......@@ -2259,3 +2259,9 @@ form .form_label {
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: #333333;
}
.list_lock_on {
color: #839496;
}
......@@ -577,7 +577,7 @@ line {
font-weight: bold;
}
.list_sort {
margin-right: 30px;
margin-right: 20px;
float: right;
}
/*style segmenter element*/
......@@ -1502,7 +1502,7 @@ h3 .uid {
#db_table_container {
overflow-y: scroll;
overflow-x: hidden;
height: calc(100% -30px);
height: calc(100% - 30px);
position: relative;
}
#db_fixed_header {
......@@ -2260,3 +2260,9 @@ form .form_label {
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: #cccccc;
}
.list_lock_on {
color: #657b83;
}
......@@ -2257,6 +2257,12 @@ form .form_label {
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: #cccccc;
}
.list_lock_on {
color: #657b83;
}
body {
line-height: 20px;
}
......
......@@ -2252,6 +2252,12 @@ form .form_label {
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: #333333;
}
.list_lock_on {
color: #777777;
}
#resolution5 {
opacity: 0;
}
......
......@@ -2254,6 +2254,12 @@ form .form_label {
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: #cccccc;
}
.list_lock_on {
color: #657b83;
}
#mid-container {
font-size: 125%;
}
......
......@@ -723,7 +723,7 @@ line {
}
.list_sort{
margin-right : 30px;
margin-right : 20px;
float: right;
}
......@@ -1714,7 +1714,7 @@ h3 .uid {
#db_table_container{
overflow-y: scroll;
overflow-x: hidden;
height: calc(100% -30px);
height: calc(100% - 30px);
position: relative;
}
......@@ -2602,4 +2602,12 @@ form {
pointer-events: none;
opacity: 0.4;
cursor: auto;
}
.list_lock_off {
color: @border;
}
.list_lock_on {
color: @default;
}
\ No newline at end of file
......@@ -177,12 +177,19 @@
</div>
<div class="menu" id="filter_menu" onmouseenter="builder.build_displaySelector();" onmouseover="showSelector('filterSelector');" > filter
<div id="filterSelector" class="selector"><div>
<div id="filterSelector" class="selector">
<div>
<div class="menu_box">
<span id="top_label"></span></br>
<input id="top_slider" type="range" min="5" max="100" step="5" value="10" onchange="m.displayTop(this.value)" />
<span id="top_label"></span></br>
<input id="top_slider" type="range" min="5" max="100" step="5" value="10" onchange="m.displayTop(this.value)" />
</div>
</div></div>
<div class="menu_box">
<div id="filter_switch_sample" title="Hide clones that are not present in the current sample">
<input id="filter_switch_sample_check" type="checkbox"></input> Focus on clones of one sample
</div>
</div>
</div>
</div>
</div>
<div class="menu" id="settings_menu" onmouseenter="builder.build_settings();" onmouseover=" showSelector('settingsSelector');" > settings
......
......@@ -391,6 +391,13 @@ Builder.prototype = {
document.getElementById("top_slider")
.max = max_top;
// init switch onlyOneSample
var onlyOneSample = document.getElementById("filter_switch_sample_check")
onlyOneSample.checked = this.m.show_only_one_sample
//init notation
if (this.m.notation_type == "scientific") {
document.getElementById("notation").checked = true
......
......@@ -1333,9 +1333,12 @@ Clone.prototype = {
if (isCluster) {
html += header("clone")
html += row_1("clone name", this.getName())
html += row_1("clone short name", this.getShortName())
html += "<tr><td>clone size (n-reads (total reads))"
if (this.hasSizeConstant()){
html += row_1("clone short name", this.getShortName())
html += "<tr><td>clone size (n-reads (total reads))"
} else if (this.hasSizeDistrib()) {
html += "<tr><td title='Current size; depending of the number of clones curently not filtered'>current clone size<br/>(n-reads (total reads))"
}
if (this.normalized_reads && this.m.normalization_mode == this.m.NORM_EXTERNAL) {
html += "<br />[normalized]"
}
......@@ -1346,7 +1349,7 @@ Clone.prototype = {
if (this.normalized_reads && this.m.normalization_mode == this.m.NORM_EXTERNAL) {
html += "<br />[" + this.getReads(this.m.samples.order[j]).toFixed(2) + "]"
}
if (typeof this.m.db_key.config != 'undefined' ) {
if (typeof this.m.db_key.config != 'undefined' && this.hasSizeConstant()) {
html += "&emsp;"
var sample_set_id = this.m.samples.sequence_file_id[this.m.samples.order[j]];
call_reads = "db.get_read('" + this.id + "', "+ this.index +", " + sample_set_id + ')';
......@@ -1390,13 +1393,21 @@ Clone.prototype = {
}
// abundance info
html += "<tr><td>size (n-reads (total reads))</td>"
if (this.hasSizeConstant()) {
html += "<tr><td>size (n-reads (total reads))</td>"
} else {
html += "<tr><td>total clones size<br/>(n-reads (total reads))</td>"
}
for (var l = 0; l < time_length; l++) {
html += "<td>" + this.get('reads',this.m.samples.order[l]) +
" (" + this.m.reads.segmented[this.m.samples.order[l]] + ")</td>"
}
html += "</tr>"
html += "<tr><td>size (%)</td>"
if (this.hasSizeConstant()) {
html += "<tr><td>size (%)</td>"
} else {
html += "<tr><td>total size (%)</td>"
}
for (var m = 0; m < time_length; m++) {
html += "<td>" + this.getStrSequenceSize(this.m.samples.order[m]) + "</td>"
}
......@@ -1404,9 +1415,13 @@ Clone.prototype = {
//segmentation info
html += header("segmentation" +
if (this.hasSizeConstant()) {
html += header("segmentation" +
" <button type='button' onclick='m.clones["+ this.index +"].toggle()'>edit</button>" + //Use to hide/display lists
this.getHTMLModifState()) // icon if manual changement
} else {
html += header("segmentation")
}
if (typeof this.stats != 'undefined'){
var total_stat = [];
......
......@@ -372,8 +372,17 @@ Database.prototype = {
if ($option.attr('required_files') == "1"){
$(".file_2").hide();
$(".upload_file").val("");
$(".upload_field").each(function() {
$(this).prop("required", false);
});
}else{
$(".file_2").show();
if ($(".is_editing").length == 0) {
// Not editing a sample, but creating new ones
$(".upload_field").each(function() {
$(this).prop("required", true);
});
}
}
},
......
......@@ -351,6 +351,8 @@ FileFormBuilder.prototype.build_file_field = function(id, hidden) {
var i = this.build_input('upload_' + id, 'upload_field', 'file'+id, 'file', 'file');
if (this.source) {
i.disabled = true;
} else {
i.required = true;
}
i.title = "(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)";
d.appendChild(i);
......
......@@ -581,9 +581,17 @@ Graph.prototype = {
if (clone.top > self.display_limit)return ' M 0,' + self.resizeH;
var size = []
var selected_point = this.m.t
var value_selected_point = this.m.clone(id).getSize(selected_point)
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])
// bypass clone size if it is not present in the current timepoint; TODO, add a switch on this behavior
if (this.m.show_only_one_sample && value_selected_point == 0) {
size[i] = 0
} else {
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])
}
}
var x = this.graph_col[0];
......
......@@ -43,16 +43,17 @@ function List(id_list, id_data, model, database) {
this.index = [];
this.index_cluster = [];
this.index_data = {};
this.sort_lock = true; // By default, lock the list in the current state
this.build();
this.sort_option = {
"-" : function () {},
"size" : function(){self.sortListBy(function(id){return self.m.clone(id).getSize();})},
"V/5'" : function(){self.sortListByV()},
"J/3'" : function(){self.sortListByJ()}
}
this.sort_option_selected = "size"; // Store the selected sort method
this.selectedAxis = {};
}
......@@ -281,6 +282,11 @@ List.prototype = {
sort.className = "list_sort_select"
sort.onchange = function() {
self.sort_option[this.value]()
self.sort_option_selected = this.value
// close the lock
self.sort_lock = true
var div = document.getElementById("div_sortLock")
div.className = "icon-lock-1 list_lock_on"
}
for (var key in this.sort_option) {
......@@ -292,6 +298,27 @@ List.prototype = {
sort_span.appendChild(document.createTextNode("sort by "));
sort_span.appendChild(sort);
var lock_div = document.createElement("icon")
lock_div.id = "div_sortLock"
lock_div.className = "icon-lock-1 list_lock_on"
lock_div.title = "Keep list sorted"
lock_div.onclick = function(){
var div = document.getElementById("div_sortLock")
if (self.sort_lock == true){
self.sort_lock = false
div.className = "icon-lock-open list_lock_off"
div.title = "Freeze list"
// Apply sort method at unlock
self.sort_option[self.sort_option_selected]()
} else {
self.sort_lock = true
div.className = "icon-lock-1 list_lock_on"
div.title = "Keep list sorted"
}
}
sort_span.appendChild( lock_div )
var axis_span = document.createElement('span');
axis_span.className = "list_axis devel-mode";
......@@ -344,8 +371,10 @@ List.prototype = {
this.updateElem(list);
this.update_data_list()
//TODO check order
document.getElementById("list_sort_select").selectedIndex = 0;
// Apply selected sort function if no sort lock
if (this.sort_lock == false){
this.sort_option[this.sort_option_selected]()
}
},
/**
......
......@@ -126,6 +126,14 @@ Model.prototype = {
$(this).removeClass('hovered');
});
this.show_only_one_sample = false
$("#filter_switch_sample").click(function(){
self.show_only_one_sample = !self.show_only_one_sample
var check = document.getElementById("filter_switch_sample_check")
check.checked = self.show_only_one_sample
self.update()
})
// Table of conversion between axes name and distribution names
this.distrib_convertion = {
......
......@@ -539,12 +539,25 @@ Model_loader.prototype = {
var clone = clones[k];
if (clone.segEdited) {
for (var n=0; n < this.clones.length; n++){
var newGermline = clone.germline;
// Sometime, clone of analysis file don't exist in the vidjil file (#4181)
// This is made by specific configuration with restricted locus analysis
// In these case, we create the newGermline into the model
// If newGermline don't exist, create an empty list for them
if (this.reads.germline[newGermline] == undefined){
console.default.log(" creation germline: " + newGermline)
this.reads.germline[newGermline] = Array.apply(null, Array(this.samples.number)).map(function (x, i) { return 0; })
}
// Same for system_available
if (this.system_available.indexOf(newGermline) == -1){
this.system_available.push(newGermline)
}
if (clone.id == this.clones[n].id){
this.clones[n].segEdited = true;
// Apply this.reads.germline changment
for (var time =0; time< this.reads.segmented.length; time ++) {
var oldGermline = this.clones[n].germline;
var newGermline = clone.germline;
if(oldGermline != "custom") {this.reads.germline[oldGermline][time] -= this.clones[n].reads[time];}
if(newGermline != "custom") {this.reads.germline[newGermline][time] += this.clones[n].reads[time];}
if (newGermline == "custom" && newGermline != oldGermline) {
......
......@@ -292,16 +292,35 @@ QUnit.test("name, informations, getHtmlInfo", function(assert) {
dclone.defineCompatibleClones()
dclone.updateReadsDistribClones()
html = m.clones[0].getHtmlInfo();
// Sequence
var notinclude = html.includes("<td>sequence</td>")
assert.notOk(notinclude, "getHtmlInfo: if no sequence, no field sequence");
console.log( html)
// Representative
var include = html.includes("<td class='header' colspan='2'>representative sequence</td>")
assert.ok(include, "getHtmlInfo: if clone distrib, keep field 'representative sequence'");
// Representative
include = html.includes("total clones size")
assert.ok(include, "getHtmlInfo: if clone distrib, other line name; 'clone size'");
// Representative
include = html.includes("current clone size")
assert.ok(include, "getHtmlInfo: if no sequence, field 'current clone size'");
// gene V
assert.includes(html, "<tr><td>V gene (or 5')</td>",
"getHtmlInfo: distrib clone with seg5 have field segment V");
// Sequence
var notinclude = html.includes("<td>sequence</td>")