sequenceserver 2.0.0.beta3 → 2.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.eslintrc.json +36 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +53 -20
- data/AppImage/recipe.yml +15 -0
- data/AppImage/sequenceserver.desktop +8 -0
- data/AppImage/sequenceserver.png +0 -0
- data/AppImage/sequenceserver.sh +11 -0
- data/README.md +79 -46
- data/bin/sequenceserver +4 -4
- data/lib/sequenceserver/version.rb +1 -1
- data/package.json +2 -0
- data/public/css/grapher.css +3 -0
- data/public/css/sequenceserver.css +17 -6
- data/public/css/sequenceserver.min.css +3 -3
- data/public/js/circos.js +515 -491
- data/public/js/grapher.js +12 -6
- data/public/js/hits_overview.js +321 -308
- data/public/js/hsp.js +12 -7
- data/public/js/length_distribution.js +241 -234
- data/public/js/report.js +196 -174
- data/public/js/search.js +3 -3
- data/public/js/sequenceserver.js +9 -9
- data/public/js/utils.js +17 -10
- data/public/js/visualisation_helpers.js +77 -77
- data/public/sequenceserver-report.min.js +17 -17
- data/public/sequenceserver-search.min.js +1 -1
- data/public/vendor/github/nicgirault/circosJs@1.7.0/dist/circosJS.js +1 -5
- data/sequenceserver.gemspec +1 -2
- data/spec/blast_versions/blast_2.2.30/blast_2.2.30_spec.rb +13 -13
- data/spec/blast_versions/blast_2.2.30/import_spec_capybara_local_2.2.30.rb +555 -25
- data/spec/blast_versions/blast_2.2.31/blast_2.2.31_spec.rb +13 -13
- data/spec/blast_versions/blast_2.2.31/import_spec_capybara_local_2.2.31.rb +558 -24
- data/spec/blast_versions/blast_2.3.0/blast_2.3.0_spec.rb +13 -13
- data/spec/blast_versions/blast_2.3.0/import_spec_capybara_local_2.3.0.rb +561 -26
- data/spec/blast_versions/blast_2.4.0/blast_2.4.0_spec.rb +13 -13
- data/spec/blast_versions/blast_2.4.0/import_spec_capybara_local_2.4.0.rb +561 -25
- data/spec/blast_versions/blast_2.5.0/blast_2.5.0_spec.rb +13 -13
- data/spec/blast_versions/blast_2.5.0/import_spec_capybara_local_2.5.0.rb +558 -24
- data/spec/blast_versions/blast_2.6.0/blast_2.6.0_spec.rb +13 -13
- data/spec/blast_versions/blast_2.6.0/import_spec_capybara_local_2.6.0.rb +559 -24
- data/spec/blast_versions/blast_2.7.1/blast_2.7.1_spec.rb +13 -13
- data/spec/blast_versions/blast_2.7.1/import_spec_capybara_local_2.7.1.rb +559 -28
- data/spec/blast_versions/blast_2.8.1/blast_2.8.1_spec.rb +13 -13
- data/spec/blast_versions/blast_2.8.1/import_spec_capybara_local_2.8.1.rb +559 -27
- data/spec/blast_versions/blast_2.9.0/blast_2.9.0_spec.rb +13 -13
- data/spec/blast_versions/blast_2.9.0/import_spec_capybara_local_2.9.0.rb +557 -25
- data/spec/blast_versions/diamond_0.9.24/diamond_0.9.24_spec.rb +13 -13
- data/spec/blast_versions/diamond_0.9.24/import_spec_capybara_local_0.9.24.rb +219 -21
- data/spec/capybara_spec.rb +25 -28
- data/spec/download_helper.rb +6 -3
- data/spec/sequences/MH011443_1_gi_1486783306_gb_MH011443_1.txt +6 -0
- data/spec/sequences/MH011443_1_gi_1486783307_gb_AYF55702_1.txt +6 -0
- data/spec/sequences/MH011443_1_gi_1528997474_gb_MH447967_1.txt +30 -0
- data/spec/sequences/MH011443_1_sp_P04637_P53_HUMAN.txt +6 -0
- data/spec/sequences/alignment-35_hits_diamond_blastp.txt +210 -0
- data/spec/sequences/alignment-35_hits_diamond_blastx.txt +210 -0
- data/spec/sequences/alignment-3_hits.txt +18 -0
- data/spec/sequences/alignment-40_hits_blastn.txt +246 -0
- data/spec/sequences/alignment-40_hits_blastp.txt +240 -0
- data/spec/sequences/alignment-40_hits_blastp_2.2.30.txt +240 -0
- data/spec/sequences/alignment-40_hits_blastx.txt +240 -0
- data/spec/sequences/alignment-40_hits_tblastn.txt +240 -0
- data/spec/sequences/alignment-40_hits_tblastn_2.2.30.txt +240 -0
- data/spec/sequences/alignment-40_hits_tblastx.txt +2664 -0
- data/spec/sequences/alignment-4_hits.txt +24 -0
- data/spec/sequences/alignment-4_hits_blastn.txt +24 -0
- data/spec/sequences/alignment-4_hits_blastp.txt +24 -0
- data/spec/sequences/alignment-4_hits_blastp_2.2.30.txt +24 -0
- data/spec/sequences/alignment-4_hits_blastx.txt +24 -0
- data/spec/sequences/alignment-4_hits_diamond_blastp.txt +24 -0
- data/spec/sequences/alignment-4_hits_diamond_blastx.txt +24 -0
- data/spec/sequences/alignment-4_hits_tblastn.txt +24 -0
- data/spec/sequences/alignment-4_hits_tblastn_2.2.30.txt +24 -0
- data/spec/sequences/alignment-4_hits_tblastx.txt +318 -0
- data/spec/sequences/sp_P04637_P53_HUMAN_gi_1099170394_ref_XP_018868681_1.txt +6 -0
- data/spec/sequences/sp_P04637_P53_HUMAN_gi_120407068_ref_NP_000537_3.txt +6 -0
- data/spec/sequences/sp_P04637_P53_HUMAN_gi_1484127324_gb_MG595988_1.txt +6 -0
- data/spec/sequences/sp_P04637_P53_HUMAN_gi_395440626_gb_JQ694049_1.txt +6 -0
- data/spec/sequences/sp_P04637_P53_HUMAN_sp_P04637_P53_HUMAN.txt +6 -0
- data/spec/spec_helper.rb +3 -3
- metadata +67 -57
- data/.eslintrc +0 -213
- data/Rakefile +0 -8
- data/spec/dotdir/blast_2.4.0/blastn/TBLASTN_XML_2.4.0.xml +0 -1181
- data/spec/dotdir/blast_2.5.0/blastn/BLASTN_LONG_XML_2.5.0.xml +0 -18813
- data/spec/import_spec_capybara_local.rb +0 -61
data/public/js/report.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import './sequenceserver' // for custom $.tooltip function
|
1
|
+
import './sequenceserver'; // for custom $.tooltip function
|
2
2
|
import React from 'react';
|
3
3
|
import _ from 'underscore';
|
4
4
|
|
@@ -19,8 +19,8 @@ import showErrorModal from './error_modal';
|
|
19
19
|
*/
|
20
20
|
var downloadFASTA = function (sequence_ids, database_ids) {
|
21
21
|
var form = $('<form/>').attr('method', 'post').attr('action', 'get_sequence');
|
22
|
-
addField(
|
23
|
-
addField(
|
22
|
+
addField('sequence_ids', sequence_ids);
|
23
|
+
addField('database_ids', database_ids);
|
24
24
|
form.appendTo('body').submit().remove();
|
25
25
|
|
26
26
|
function addField(name, val) {
|
@@ -28,7 +28,7 @@ var downloadFASTA = function (sequence_ids, database_ids) {
|
|
28
28
|
$('<input>').attr('type', 'hidden').attr('name', name).val(val)
|
29
29
|
);
|
30
30
|
}
|
31
|
-
}
|
31
|
+
};
|
32
32
|
|
33
33
|
/**
|
34
34
|
* Base component of report page. This component is later rendered into page's
|
@@ -86,24 +86,24 @@ var Report = React.createClass({
|
|
86
86
|
$.getJSON(location.pathname + '.json')
|
87
87
|
.complete(function (jqXHR) {
|
88
88
|
switch (jqXHR.status) {
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
89
|
+
case 202:
|
90
|
+
var interval;
|
91
|
+
if (intervals.length === 1) {
|
92
|
+
interval = intervals[0];
|
93
|
+
}
|
94
|
+
else {
|
95
|
+
interval = intervals.shift();
|
96
|
+
}
|
97
|
+
setTimeout(poll, interval);
|
98
|
+
break;
|
99
|
+
case 200:
|
100
|
+
component.updateState(jqXHR.responseJSON);
|
101
|
+
break;
|
102
|
+
case 404:
|
103
|
+
case 400:
|
104
|
+
case 500:
|
105
|
+
showErrorModal(jqXHR.responseJSON);
|
106
|
+
break;
|
107
107
|
}
|
108
108
|
});
|
109
109
|
}
|
@@ -188,19 +188,14 @@ var Report = React.createClass({
|
|
188
188
|
<div className={this.shouldShowSidebar() ?
|
189
189
|
'col-md-9' : 'col-md-12'}>
|
190
190
|
{ this.overviewJSX() }
|
191
|
-
{ this.
|
192
|
-
? <Circos queries={this.state.queries}
|
193
|
-
program={this.state.program} collapsed="true"/>
|
194
|
-
: <span></span> }
|
191
|
+
{ this.circosJSX() }
|
195
192
|
{
|
196
193
|
_.map(this.state.queries, _.bind(function (query) {
|
197
194
|
return (
|
198
|
-
<Query key={
|
199
|
-
program={this.state.program} querydb={this.state.querydb}
|
200
|
-
|
201
|
-
|
202
|
-
imported_xml={this.state.imported_xml} />
|
203
|
-
);
|
195
|
+
<Query key={'Query_'+query.id} query={query} showQueryCrumbs={this.state.num_queries > 1}
|
196
|
+
selectHit={this.selectHit} program={this.state.program} querydb={this.state.querydb}
|
197
|
+
veryBig={this.state.veryBig} imported_xml={this.state.imported_xml} />
|
198
|
+
);
|
204
199
|
}, this))
|
205
200
|
}
|
206
201
|
</div>
|
@@ -214,25 +209,36 @@ var Report = React.createClass({
|
|
214
209
|
overviewJSX: function () {
|
215
210
|
return (
|
216
211
|
<div className="overview">
|
217
|
-
<
|
212
|
+
<p className="text-monospace">
|
218
213
|
{this.state.program_version}{this.state.submitted_at
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
this.state.querydb.map((db) => { return db.title }).join(
|
224
|
-
}
|
225
|
-
|
214
|
+
&& `, query submitted on ${this.state.submitted_at}`}
|
215
|
+
</p>
|
216
|
+
<p className="text-monospace">
|
217
|
+
Databases: {
|
218
|
+
this.state.querydb.map((db) => { return db.title; }).join(', ')
|
219
|
+
} ({this.state.stats.nsequences} sequences,
|
220
|
+
{this.state.stats.ncharacters} characters)
|
221
|
+
</p>
|
222
|
+
<p className="text-monospace">
|
226
223
|
Parameters: {
|
227
224
|
_.map(this.state.params, function (val, key) {
|
228
|
-
return key +
|
229
|
-
}).join(
|
225
|
+
return key + ' ' + val;
|
226
|
+
}).join(', ')
|
230
227
|
}
|
231
|
-
</
|
228
|
+
</p>
|
232
229
|
</div>
|
233
230
|
);
|
234
|
-
|
231
|
+
},
|
235
232
|
|
233
|
+
/**
|
234
|
+
* Return JSX for circos if we have at least one hit.
|
235
|
+
*/
|
236
|
+
circosJSX: function () {
|
237
|
+
return this.atLeastTwoHits()
|
238
|
+
? <Circos queries={this.state.queries}
|
239
|
+
program={this.state.program} collapsed="true"/>
|
240
|
+
: <span></span>;
|
241
|
+
},
|
236
242
|
|
237
243
|
// Controller //
|
238
244
|
|
@@ -245,12 +251,19 @@ var Report = React.createClass({
|
|
245
251
|
return this.state.queries.length >= 1;
|
246
252
|
},
|
247
253
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
254
|
+
/**
|
255
|
+
* Returns true if we have at least one hit.
|
256
|
+
*/
|
257
|
+
atLeastOneHit: function () {
|
258
|
+
return this.state.queries.some(query => query.hits.length > 0);
|
259
|
+
},
|
260
|
+
|
261
|
+
atLeastTwoHits: function () {
|
262
|
+
var hit_num = 0;
|
263
|
+
return this.state.queries.some(query => {
|
264
|
+
hit_num += query.hits.length;
|
265
|
+
return hit_num > 1;
|
252
266
|
});
|
253
|
-
return !(cnt == this.state.queries.length);
|
254
267
|
},
|
255
268
|
|
256
269
|
/**
|
@@ -265,13 +278,12 @@ var Report = React.createClass({
|
|
265
278
|
},
|
266
279
|
|
267
280
|
/**
|
268
|
-
* Returns true if index should be shown in the sidebar.
|
269
|
-
*
|
270
|
-
* Index is not shown in the sidebar if there are more than eight queries
|
271
|
-
* in total.
|
281
|
+
* Returns true if index should be shown in the sidebar. Index is shown
|
282
|
+
* only for 2 and 8 queries.
|
272
283
|
*/
|
273
284
|
shouldShowIndex: function () {
|
274
|
-
|
285
|
+
var num_queries = this.state.queries.length;
|
286
|
+
return num_queries >= 2 && num_queries <= 8;
|
275
287
|
},
|
276
288
|
|
277
289
|
/**
|
@@ -309,7 +321,7 @@ var Report = React.createClass({
|
|
309
321
|
* Prevents folding of hits during text-selection.
|
310
322
|
*/
|
311
323
|
preventCollapseOnSelection: function () {
|
312
|
-
$('body').on('mousedown',
|
324
|
+
$('body').on('mousedown', '.hit > .section-header > h4', function (event) {
|
313
325
|
var $this = $(this);
|
314
326
|
$this.on('mouseup mousemove', function handler(event) {
|
315
327
|
if (event.type === 'mouseup') {
|
@@ -355,7 +367,7 @@ var Report = React.createClass({
|
|
355
367
|
*/
|
356
368
|
selectHit: function (id) {
|
357
369
|
|
358
|
-
var checkbox = $(
|
370
|
+
var checkbox = $('#' + id);
|
359
371
|
var num_checked = $('.hit-links :checkbox:checked').length;
|
360
372
|
|
361
373
|
if (!checkbox || !checkbox.val()) {
|
@@ -366,7 +378,7 @@ var Report = React.createClass({
|
|
366
378
|
|
367
379
|
// Highlight selected hit and enable 'Download FASTA/Alignment of
|
368
380
|
// selected' links.
|
369
|
-
if (checkbox.is(
|
381
|
+
if (checkbox.is(':checked')) {
|
370
382
|
$hit.find('.section-content').addClass('glow');
|
371
383
|
$('.download-alignment-of-selected').enable();
|
372
384
|
$('.download-fasta-of-selected').enable();
|
@@ -406,7 +418,11 @@ var Query = React.createClass({
|
|
406
418
|
* Returns the id of query.
|
407
419
|
*/
|
408
420
|
domID: function () {
|
409
|
-
return
|
421
|
+
return 'Query_' + this.props.query.number;
|
422
|
+
},
|
423
|
+
|
424
|
+
queryLength: function () {
|
425
|
+
return this.props.query.length;
|
410
426
|
},
|
411
427
|
|
412
428
|
/**
|
@@ -423,59 +439,57 @@ var Query = React.createClass({
|
|
423
439
|
<div className="resultn" id={this.domID()}
|
424
440
|
data-query-len={this.props.query.length}
|
425
441
|
data-algorithm={this.props.program}>
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
</
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
}
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
className="section-content">
|
466
|
-
<p>
|
467
|
-
Query length: {this.props.query.length}
|
468
|
-
</p>
|
469
|
-
<br/>
|
470
|
-
<br/>
|
471
|
-
<p>
|
472
|
-
<strong> ****** No hits found ****** </strong>
|
473
|
-
</p>
|
474
|
-
</div>
|
475
|
-
)
|
442
|
+
{ this.headerJSX() }
|
443
|
+
{ this.numhits() && this.hitsListJSX() || this.noHitsJSX() }
|
444
|
+
</div>
|
445
|
+
);
|
446
|
+
},
|
447
|
+
|
448
|
+
headerJSX: function () {
|
449
|
+
var meta = `length: ${this.queryLength().toLocaleString()}`;
|
450
|
+
if (this.props.showQueryCrumbs) {
|
451
|
+
meta = `query ${this.props.query.number}, ` + meta;
|
452
|
+
}
|
453
|
+
return <div className="section-header">
|
454
|
+
<h3>
|
455
|
+
Query= {this.props.query.id}
|
456
|
+
<small>{this.props.query.title}</small>
|
457
|
+
</h3>
|
458
|
+
<span className="label label-reset pos-label">{ meta }</span>
|
459
|
+
</div>;
|
460
|
+
},
|
461
|
+
|
462
|
+
hitsListJSX: function () {
|
463
|
+
return <div className="section-content">
|
464
|
+
<HitsOverview key={'GO_' + this.props.query.number} query={this.props.query} program={this.props.program} collapsed={this.props.veryBig} />
|
465
|
+
<LengthDistribution key={'LD_' + this.props.query.id} query={this.props.query} algorithm={this.props.program} collapsed="true" />
|
466
|
+
<HitsTable key={'HT_' + this.props.query.number} query={this.props.query} imported_xml={this.props.imported_xml} />
|
467
|
+
<div id="hits">
|
468
|
+
{
|
469
|
+
_.map(this.props.query.hits, _.bind(function (hit) {
|
470
|
+
return (
|
471
|
+
<Hit key={'HIT_' + hit.number} hit={hit}
|
472
|
+
algorithm={this.props.program}
|
473
|
+
querydb={this.props.querydb}
|
474
|
+
query={this.props.query}
|
475
|
+
imported_xml={this.props.imported_xml}
|
476
|
+
selectHit={this.props.selectHit}
|
477
|
+
showHitCrumbs={this.numhits() > 1}
|
478
|
+
showQueryCrumbs={this.props.showQueryCrumbs} />
|
479
|
+
);
|
480
|
+
}, this))
|
476
481
|
}
|
477
482
|
</div>
|
478
|
-
|
483
|
+
</div>;
|
484
|
+
},
|
485
|
+
|
486
|
+
noHitsJSX: function () {
|
487
|
+
return <div className="section-content">
|
488
|
+
<br />
|
489
|
+
<p>
|
490
|
+
<strong> ****** No hits found ****** </strong>
|
491
|
+
</p>
|
492
|
+
</div>;
|
479
493
|
},
|
480
494
|
|
481
495
|
shouldComponentUpdate: function (nextProps, nextState) {
|
@@ -490,9 +504,9 @@ var HitsTable = React.createClass({
|
|
490
504
|
mixins: [Utils],
|
491
505
|
render: function () {
|
492
506
|
var count = 0,
|
493
|
-
|
494
|
-
|
495
|
-
|
507
|
+
hasName = _.every(this.props.query.hits, function(hit) {
|
508
|
+
return hit.sciname !== '';
|
509
|
+
});
|
496
510
|
|
497
511
|
return (
|
498
512
|
<table
|
@@ -514,9 +528,9 @@ var HitsTable = React.createClass({
|
|
514
528
|
_.map(this.props.query.hits, _.bind(function (hit) {
|
515
529
|
return (
|
516
530
|
<tr key={hit.number}>
|
517
|
-
<td className="text-left">{hit.number +
|
531
|
+
<td className="text-left">{hit.number + '.'}</td>
|
518
532
|
<td>
|
519
|
-
<a href={
|
533
|
+
<a href={'#Query_' + this.props.query.number + '_hit_' + hit.number}>
|
520
534
|
{hit.id}
|
521
535
|
</a>
|
522
536
|
</td>
|
@@ -526,7 +540,7 @@ var HitsTable = React.createClass({
|
|
526
540
|
<td className="text-right">{this.inExponential(hit.hsps[0].evalue)}</td>
|
527
541
|
<td className="text-right">{hit.identity}</td>
|
528
542
|
</tr>
|
529
|
-
)
|
543
|
+
);
|
530
544
|
}, this))
|
531
545
|
}
|
532
546
|
</tbody>
|
@@ -551,7 +565,7 @@ var Hit = React.createClass({
|
|
551
565
|
/**
|
552
566
|
* Returns length of the hit sequence.
|
553
567
|
*/
|
554
|
-
|
568
|
+
hitLength: function () {
|
555
569
|
return this.props.hit.length;
|
556
570
|
},
|
557
571
|
|
@@ -561,7 +575,7 @@ var Hit = React.createClass({
|
|
561
575
|
* Returns id that will be used for the DOM node corresponding to the hit.
|
562
576
|
*/
|
563
577
|
domID: function () {
|
564
|
-
return
|
578
|
+
return 'Query_' + this.props.query.number + '_hit_' + this.props.hit.number;
|
565
579
|
},
|
566
580
|
|
567
581
|
databaseIDs: function () {
|
@@ -593,10 +607,10 @@ var Hit = React.createClass({
|
|
593
607
|
hsp.query_id = this.props.query.id;
|
594
608
|
hsp.hit_id = this.props.hit.id;
|
595
609
|
return hsp;
|
596
|
-
}, this))
|
610
|
+
}, this));
|
597
611
|
|
598
612
|
var aln_exporter = new AlignmentExporter();
|
599
|
-
aln_exporter.export_alignments(hsps, this.props.query.id+
|
613
|
+
aln_exporter.export_alignments(hsps, this.props.query.id+'_'+this.props.hit.id);
|
600
614
|
},
|
601
615
|
|
602
616
|
|
@@ -608,7 +622,7 @@ var Hit = React.createClass({
|
|
608
622
|
|
609
623
|
// Return JSX for view sequence button.
|
610
624
|
viewSequenceButton: function () {
|
611
|
-
if (this.
|
625
|
+
if (this.hitLength() > 10000) {
|
612
626
|
return (
|
613
627
|
<button
|
614
628
|
className="btn btn-link view-sequence disabled"
|
@@ -630,49 +644,57 @@ var Hit = React.createClass({
|
|
630
644
|
|
631
645
|
render: function () {
|
632
646
|
return (
|
633
|
-
<div className="hit" id={this.domID()}
|
634
|
-
data-hit-
|
635
|
-
|
636
|
-
<div className="section-header">
|
637
|
-
<h4 data-toggle="collapse"
|
638
|
-
data-target={this.domID() + "_content"}>
|
639
|
-
<i className="fa fa-chevron-down"></i>
|
640
|
-
|
641
|
-
<span>
|
642
|
-
{this.props.hit.id}
|
643
|
-
|
644
|
-
<small>
|
645
|
-
{this.props.hit.title}
|
646
|
-
</small>
|
647
|
-
</span>
|
648
|
-
</h4>
|
649
|
-
<span className="label label-reset pos-label"
|
650
|
-
title={"Query " + this.props.query.number + ". Hit "
|
651
|
-
+ this.props.hit.number + " of "
|
652
|
-
+ this.props.query.hits.length + "."}
|
653
|
-
data-toggle="tooltip">
|
654
|
-
{this.props.hit.number + "/" + this.props.query.hits.length}
|
655
|
-
</span>
|
656
|
-
</div>
|
657
|
-
<div id={this.domID() + "_content"}
|
658
|
-
className="section-content collapse in">
|
659
|
-
{ this.hitLinks() }
|
660
|
-
<HSPOverview key={"kablammo"+this.props.query.id}
|
661
|
-
query={this.props.query} hit={this.props.hit}
|
662
|
-
algorithm={this.props.algorithm}/>
|
663
|
-
{ this.hspListJSX() }
|
664
|
-
</div>
|
647
|
+
<div className="hit" id={this.domID()} data-hit-def={this.props.hit.id}
|
648
|
+
data-hit-len={this.props.hit.length} data-hit-evalue={this.props.hit.evalue}>
|
649
|
+
{ this.headerJSX() } { this.contentJSX() }
|
665
650
|
</div>
|
666
651
|
);
|
667
652
|
},
|
668
653
|
|
654
|
+
headerJSX: function () {
|
655
|
+
var meta = `length: ${this.hitLength().toLocaleString()}`;
|
656
|
+
|
657
|
+
if (this.props.showQueryCrumbs && this.props.showHitCrumbs) {
|
658
|
+
// Multiper queries, multiple hits
|
659
|
+
meta = `hit ${this.props.hit.number} of query ${this.props.query.number}, ` + meta;
|
660
|
+
}
|
661
|
+
else if (this.props.showQueryCrumbs && !this.props.showHitCrumbs) {
|
662
|
+
// Multiple queries, single hit
|
663
|
+
meta = `the only hit of query ${this.props.query.number}, ` + meta;
|
664
|
+
}
|
665
|
+
else if (!this.props.showQueryCrumbs && this.props.showHitCrumbs) {
|
666
|
+
// Single query, multiple hits
|
667
|
+
meta = `hit ${this.props.hit.number}, ` + meta;
|
668
|
+
}
|
669
|
+
|
670
|
+
return <div className="section-header">
|
671
|
+
<h4 data-toggle="collapse" data-target={this.domID() + '_content'}>
|
672
|
+
<i className="fa fa-chevron-down"></i>
|
673
|
+
<span>
|
674
|
+
{this.props.hit.id}
|
675
|
+
<small>{this.props.hit.title}</small>
|
676
|
+
</span>
|
677
|
+
</h4>
|
678
|
+
<span className="label label-reset pos-label">{ meta }</span>
|
679
|
+
</div>;
|
680
|
+
},
|
681
|
+
|
682
|
+
contentJSX: function () {
|
683
|
+
return <div id={this.domID() + '_content'} className="section-content collapse in">
|
684
|
+
{ this.hitLinks() }
|
685
|
+
<HSPOverview key={'kablammo' + this.props.query.id} query={this.props.query}
|
686
|
+
hit={this.props.hit} algorithm={this.props.algorithm} />
|
687
|
+
{ this.hspListJSX() }
|
688
|
+
</div>;
|
689
|
+
},
|
690
|
+
|
669
691
|
hitLinks: function () {
|
670
692
|
return (
|
671
693
|
<div className="hit-links">
|
672
694
|
<label>
|
673
|
-
<input type="checkbox" id={this.domID() +
|
695
|
+
<input type="checkbox" id={this.domID() + '_checkbox'}
|
674
696
|
value={this.accession()} onChange={function () {
|
675
|
-
this.props.selectHit(this.domID() +
|
697
|
+
this.props.selectHit(this.domID() + '_checkbox');
|
676
698
|
}.bind(this)} data-target={'#' + this.domID()}
|
677
699
|
/> Select
|
678
700
|
</label>
|
@@ -714,10 +736,10 @@ var Hit = React.createClass({
|
|
714
736
|
return <HSP key={hsp.number}
|
715
737
|
algorithm={this.props.algorithm}
|
716
738
|
queryNumber={this.props.query.number}
|
717
|
-
hitNumber={this.props.hit.number} hsp={hsp}
|
739
|
+
hitNumber={this.props.hit.number} hsp={hsp}/>;
|
718
740
|
}, this)
|
719
741
|
}
|
720
|
-
</div
|
742
|
+
</div>;
|
721
743
|
}
|
722
744
|
});
|
723
745
|
|
@@ -886,7 +908,7 @@ var SequenceViewer = (function () {
|
|
886
908
|
sequences: response.sequences,
|
887
909
|
error_msgs: response.error_msgs,
|
888
910
|
requestCompleted: true
|
889
|
-
})
|
911
|
+
});
|
890
912
|
}, this))
|
891
913
|
.fail(function (jqXHR, status, error) {
|
892
914
|
showErrorModal(jqXHR, function () {
|
@@ -941,11 +963,11 @@ var SideBar = React.createClass({
|
|
941
963
|
hsp.hit_id = hit.id;
|
942
964
|
hsp.query_id = query.id;
|
943
965
|
hsps_arr.push(hsp);
|
944
|
-
})
|
945
|
-
})
|
966
|
+
});
|
967
|
+
});
|
946
968
|
}, this));
|
947
969
|
console.log('len '+hsps_arr.length);
|
948
|
-
aln_exporter.export_alignments(hsps_arr,
|
970
|
+
aln_exporter.export_alignments(hsps_arr, 'alignment-'+sequence_ids.length+'_hits');
|
949
971
|
return false;
|
950
972
|
},
|
951
973
|
|
@@ -967,7 +989,7 @@ var SideBar = React.createClass({
|
|
967
989
|
}
|
968
990
|
});
|
969
991
|
}, this));
|
970
|
-
aln_exporter.export_alignments(hsps_arr,
|
992
|
+
aln_exporter.export_alignments(hsps_arr, 'alignment-'+sequence_ids.length+'_hits');
|
971
993
|
return false;
|
972
994
|
},
|
973
995
|
|
@@ -979,29 +1001,29 @@ var SideBar = React.createClass({
|
|
979
1001
|
{ this.props.shouldShowIndex && this.index() }
|
980
1002
|
{ this.downloads() }
|
981
1003
|
</div>
|
982
|
-
)
|
1004
|
+
);
|
983
1005
|
},
|
984
1006
|
|
985
1007
|
index: function () {
|
986
1008
|
return (
|
987
1009
|
<div className="index">
|
988
1010
|
<div
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
1011
|
+
className="section-header">
|
1012
|
+
<h4>
|
1013
|
+
{ this.summary() }
|
1014
|
+
</h4>
|
993
1015
|
</div>
|
994
1016
|
<ul
|
995
1017
|
className="nav hover-reset active-bold">
|
996
1018
|
{
|
997
1019
|
_.map(this.props.data.queries, _.bind(function (query) {
|
998
1020
|
return (
|
999
|
-
<li key={
|
1021
|
+
<li key={'Side_bar_'+query.id}>
|
1000
1022
|
<a
|
1001
1023
|
className="nowrap-ellipsis hover-bold"
|
1002
|
-
href={
|
1003
|
-
title={
|
1004
|
-
{
|
1024
|
+
href={'#Query_' + query.number}
|
1025
|
+
title={'Query= ' + query.id + ' ' + query.title}>
|
1026
|
+
{'Query= ' + query.id}
|
1005
1027
|
</a>
|
1006
1028
|
</li>
|
1007
1029
|
);
|
@@ -1019,7 +1041,7 @@ var SideBar = React.createClass({
|
|
1019
1041
|
|
1020
1042
|
return (
|
1021
1043
|
program.toUpperCase() + ': ' +
|
1022
|
-
numqueries + ' ' + (numqueries > 1 ? 'queries' : 'query') +
|
1044
|
+
numqueries + ' ' + (numqueries > 1 ? 'queries' : 'query') + ', ' +
|
1023
1045
|
numquerydb + ' ' + (numquerydb > 1 ? 'databases' : 'database')
|
1024
1046
|
);
|
1025
1047
|
},
|
@@ -1068,7 +1090,7 @@ var SideBar = React.createClass({
|
|
1068
1090
|
name, alignment length, mismatches, gaps, identity,
|
1069
1091
|
start and end coordinates, e value, bitscore, query
|
1070
1092
|
coverage per subject and per HSP."
|
1071
|
-
href={
|
1093
|
+
href={'download/' + this.props.data.search_id + '.std_tsv'}>
|
1072
1094
|
Standard tabular report
|
1073
1095
|
</a>
|
1074
1096
|
</li>
|
@@ -1080,7 +1102,7 @@ var SideBar = React.createClass({
|
|
1080
1102
|
accessions, and length; alignment details;
|
1081
1103
|
taxonomy details of subject sequence(s) and
|
1082
1104
|
query coverage per subject and per HSP."
|
1083
|
-
href={
|
1105
|
+
href={'download/' + this.props.data.search_id + '.full_tsv'}>
|
1084
1106
|
Full tabular report
|
1085
1107
|
</a>
|
1086
1108
|
</li>
|
@@ -1089,7 +1111,7 @@ var SideBar = React.createClass({
|
|
1089
1111
|
!this.props.data.imported_xml && <li>
|
1090
1112
|
<a className="download" data-toggle="tooltip"
|
1091
1113
|
title="Results in XML format."
|
1092
|
-
href={
|
1114
|
+
href={'download/' + this.props.data.search_id + '.xml'}>
|
1093
1115
|
Full XML report
|
1094
1116
|
</a>
|
1095
1117
|
</li>
|