sequenceserver 2.0.0.rc8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sequenceserver +22 -30
- data/lib/sequenceserver/api_errors.rb +5 -1
- data/lib/sequenceserver/blast/constants.rb +1 -1
- data/lib/sequenceserver/blast/hit.rb +5 -16
- data/lib/sequenceserver/blast/job.rb +9 -18
- data/lib/sequenceserver/blast/report.rb +5 -3
- data/lib/sequenceserver/config.rb +4 -1
- data/lib/sequenceserver/database.rb +69 -9
- data/lib/sequenceserver/job.rb +1 -1
- data/lib/sequenceserver/makeblastdb.rb +40 -45
- data/lib/sequenceserver/routes.rb +4 -0
- data/lib/sequenceserver/version.rb +1 -1
- data/lib/sequenceserver.rb +15 -11
- data/public/config.js +143 -142
- data/public/css/fonts.css +23 -22
- data/public/css/grapher.css +598 -594
- data/public/css/sequenceserver.css +86 -24
- data/public/css/sequenceserver.min.css +2 -2
- data/public/js/alignment_exporter.js +14 -14
- data/public/js/databases_tree.js +215 -0
- data/public/js/download_fasta.js +1 -1
- data/public/js/hit.js +6 -2
- data/public/js/hits_overview.js +1 -1
- data/public/js/length_distribution.js +5 -5
- data/public/js/query.js +4 -7
- data/public/js/report.js +12 -24
- data/public/js/search.js +21 -2
- data/public/js/sidebar.js +4 -4
- data/public/js/svgExporter.js +12 -12
- data/public/js/visualisation_helpers.js +4 -5
- data/public/sequenceserver-report.min.js +11 -11
- data/public/sequenceserver-search.min.js +15 -11
- data/public/vendor/github/vakata/jstree@3.3.8/LICENSE-MIT +22 -0
- data/public/vendor/github/vakata/jstree@3.3.8/README.md +663 -0
- data/public/vendor/github/vakata/jstree@3.3.8/bower.json +33 -0
- data/public/vendor/github/vakata/jstree@3.3.8/component.json +28 -0
- data/public/vendor/github/vakata/jstree@3.3.8/composer.json +46 -0
- data/public/vendor/github/vakata/jstree@3.3.8/demo/README.md +2 -0
- data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/index.html +146 -0
- data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/root.json +1 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.js +8612 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.min.js +6 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/32px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/40px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.css +1102 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.min.css +1 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/throbber.gif +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/32px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/40px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.css +1146 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.min.css +1 -0
- data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/throbber.gif +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/gruntfile.js +242 -0
- data/public/vendor/github/vakata/jstree@3.3.8/jstree.jquery.json +28 -0
- data/public/vendor/github/vakata/jstree@3.3.8/package.json +58 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/intro.js +14 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.changed.js +69 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.checkbox.js +976 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.conditionalselect.js +38 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.contextmenu.js +661 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.dnd.js +669 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.js +4931 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.massload.js +137 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.search.js +421 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.sort.js +74 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.state.js +138 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.types.js +372 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.unique.js +164 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.wholerow.js +122 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/misc.js +656 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/outro.js +1 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/sample.js +93 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/base.less +93 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/32px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/40px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.css +1102 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.less +22 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/throbber.gif +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/32px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/40px.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.css +1146 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.less +50 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/throbber.gif +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/main.less +77 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/mixins.less +104 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/themes/responsive.less +67 -0
- data/public/vendor/github/vakata/jstree@3.3.8/src/vakata-jstree.js +38 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/unit/index.html +16 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.css +244 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.js +2212 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/unit/test.js +11 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/desktop/index.html +44 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/mobile/index.html +42 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/desktop.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/home.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/home.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/mobile.png +0 -0
- data/public/vendor/github/vakata/jstree@3.3.8.js +3 -0
- data/public/vendor/system-csp-production.js +3 -3
- data/public/vendor/system-csp-production.js.map +1 -1
- data/public/vendor/system-csp-production.src.js +146 -140
- data/public/vendor/system-polyfills.js.map +1 -1
- data/public/vendor/system-polyfills.src.js +1 -0
- data/public/vendor/system.js +3 -3
- data/public/vendor/system.js.map +1 -1
- data/public/vendor/system.src.js +4771 -2383
- data/views/_options.erb +21 -0
- data/views/layout.erb +17 -18
- metadata +102 -43
- data/bin/chromedriver +0 -0
- data/bin/geckodriver +0 -0
- data/public/shims/form-core.js +0 -3
- data/public/shims/form-validation.js +0 -3
- data/public/shims/plugins/jquery.ui.position.js +0 -13
- data/public/shims/styles/shim.css +0 -1
@@ -7,28 +7,28 @@ export default class AlignmentExporter {
|
|
7
7
|
var idx = 0;
|
8
8
|
var wrapped = '';
|
9
9
|
while(true) {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
wrapped += str.substring(idx, idx + width);
|
11
|
+
idx += width;
|
12
|
+
if(idx < str.length) {
|
13
|
+
wrapped += '\n';
|
14
|
+
} else {
|
15
|
+
break;
|
16
|
+
}
|
17
17
|
}
|
18
18
|
return wrapped;
|
19
19
|
}
|
20
20
|
|
21
21
|
generate_fasta(hsps) {
|
22
22
|
|
23
|
-
var fasta =
|
23
|
+
var fasta = '';
|
24
24
|
|
25
25
|
_.each(hsps, _.bind(function (hsp) {
|
26
|
-
fasta +=
|
27
|
-
fasta += hsp.qseq+
|
28
|
-
fasta +=
|
29
|
-
fasta += hsp.midline+
|
30
|
-
fasta +=
|
31
|
-
fasta += hsp.sseq+
|
26
|
+
fasta += '>'+hsp.query_id+':'+hsp.qstart+'-'+hsp.qend+'\n';
|
27
|
+
fasta += hsp.qseq+'\n';
|
28
|
+
fasta += '>'+hsp.query_id+':'+hsp.qstart+'-'+hsp.qend+'_alignment_'+hsp.hit_id+':'+hsp.sstart+'-'+hsp.send+'\n';
|
29
|
+
fasta += hsp.midline+'\n';
|
30
|
+
fasta += '>'+hsp.hit_id+':'+hsp.sstart+'-'+hsp.send+'\n';
|
31
|
+
fasta += hsp.sseq+'\n';
|
32
32
|
}, this));
|
33
33
|
return fasta;
|
34
34
|
}
|
@@ -0,0 +1,215 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import _ from 'underscore';
|
3
|
+
import Jstree from 'vakata/jstree';
|
4
|
+
|
5
|
+
export default React.createClass({
|
6
|
+
getInitialState: function () {
|
7
|
+
return { type: '' };
|
8
|
+
},
|
9
|
+
|
10
|
+
databases: function (category) {
|
11
|
+
var databases = this.props.databases;
|
12
|
+
if (category) {
|
13
|
+
databases = _.select(databases, database => database.type === category);
|
14
|
+
}
|
15
|
+
|
16
|
+
return _.sortBy(databases, 'title');
|
17
|
+
},
|
18
|
+
|
19
|
+
nselected: function () {
|
20
|
+
return $('input[name="databases[]"]:checked').length;
|
21
|
+
},
|
22
|
+
|
23
|
+
categories: function () {
|
24
|
+
return _.uniq(_.map(this.props.databases,
|
25
|
+
_.iteratee('type'))).sort();
|
26
|
+
},
|
27
|
+
|
28
|
+
handleClick: function (database) {
|
29
|
+
var type = this.nselected() ? database.type : '';
|
30
|
+
if (type != this.state.type) this.setState({type: type});
|
31
|
+
},
|
32
|
+
|
33
|
+
handleLoadTree: function (category) {
|
34
|
+
var tree_id = '#' + category + '_database_tree';
|
35
|
+
// hack that is needed to sync the selected tree db with the hidden main db
|
36
|
+
window.jstree_node_change_timeout = null;
|
37
|
+
|
38
|
+
// when a tree database gets selected
|
39
|
+
$(tree_id).on('select_node.jstree deselect_node.jstree', function (e, data) {
|
40
|
+
if (window.jstree_node_change_timeout) {
|
41
|
+
clearTimeout(window.jstree_node_change_timeout);
|
42
|
+
window.jstree_node_change_timeout = null;
|
43
|
+
}
|
44
|
+
|
45
|
+
window.jstree_node_change_timeout = setTimeout(function(){
|
46
|
+
// uncheck all input
|
47
|
+
$('div#database_list input[type="checkbox"]:checked').click();
|
48
|
+
setTimeout(function(){
|
49
|
+
// get all selected tree dbs. Also includes folders. Therefore, the id must have a length of 32
|
50
|
+
// this id is used to find the corresponding element from the hidden main form
|
51
|
+
var selected = $(tree_id).jstree('get_selected').filter(selected => selected.length == 32);
|
52
|
+
$.each(selected, function( index, value ) {
|
53
|
+
// select hidden element to trigger original sequenceserver behavior, like blast algorithm, ...
|
54
|
+
$('input[value="'+ value + '"]').click();
|
55
|
+
});
|
56
|
+
}, 100);
|
57
|
+
}, 100);
|
58
|
+
});
|
59
|
+
|
60
|
+
$(tree_id).jstree({
|
61
|
+
'core' : {
|
62
|
+
'data': this.props.tree[category]
|
63
|
+
},
|
64
|
+
'plugins' : [ 'checkbox', 'search', 'sort' ],
|
65
|
+
'checkbox' : {
|
66
|
+
'keep_selected_style' : false
|
67
|
+
}
|
68
|
+
});
|
69
|
+
},
|
70
|
+
|
71
|
+
handleTreeSearch: function(category, tree_id, search_id) {
|
72
|
+
var search_for = $('#' + search_id).val();
|
73
|
+
$('#' + tree_id).jstree(true).search(search_for);
|
74
|
+
},
|
75
|
+
|
76
|
+
handleToggle: function (toggleState, type) {
|
77
|
+
switch (toggleState) {
|
78
|
+
case '[Select all]':
|
79
|
+
$(`.${type} .database input:not(:checked)`).click();
|
80
|
+
break;
|
81
|
+
case '[Deselect all]':
|
82
|
+
$(`.${type} .database input:checked`).click();
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
},
|
86
|
+
|
87
|
+
render: function () {
|
88
|
+
return (
|
89
|
+
<div className='form-group databases-container'>
|
90
|
+
{ _.map(this.categories(), this.renderDatabases) }
|
91
|
+
</div>
|
92
|
+
);
|
93
|
+
},
|
94
|
+
|
95
|
+
renderDatabases: function (category) {
|
96
|
+
// Panel name and column width.
|
97
|
+
var panelTitle = category[0].toUpperCase() +
|
98
|
+
category.substring(1).toLowerCase() + ' databases';
|
99
|
+
var columnClass = this.categories().length === 1 ? 'col-md-12' :
|
100
|
+
'col-md-6';
|
101
|
+
|
102
|
+
// Toggle button.
|
103
|
+
var toggleState = '[Select all]';
|
104
|
+
var toggleClass = 'btn-link';
|
105
|
+
var toggleShown = this.databases(category).length > 1 ;
|
106
|
+
var toggleDisabled = this.state.type && this.state.type !== category;
|
107
|
+
if (toggleShown && toggleDisabled) toggleClass += ' disabled';
|
108
|
+
if (!toggleShown) toggleClass += ' hidden';
|
109
|
+
if (this.nselected() === this.databases(category).length) {
|
110
|
+
toggleState = '[Deselect all]';
|
111
|
+
}
|
112
|
+
|
113
|
+
// JSX.
|
114
|
+
return (
|
115
|
+
<div className={columnClass} key={'DB_'+category}>
|
116
|
+
<div className='panel panel-default' id='database_list'>
|
117
|
+
<div className='panel-heading'>
|
118
|
+
<h4 style={{display: 'inline'}}>{panelTitle}</h4>
|
119
|
+
{
|
120
|
+
this.renderDatabaseSearch(category)
|
121
|
+
}
|
122
|
+
<button type='button' className={toggleClass} disabled={toggleDisabled} style={{display: 'none'}}
|
123
|
+
onClick={ function () { this.handleToggle(toggleState, category); }.bind(this) }>
|
124
|
+
{toggleState}
|
125
|
+
</button>
|
126
|
+
</div>
|
127
|
+
<ul className={'list-group databases ' + category} style={{display: 'none'}}>
|
128
|
+
{
|
129
|
+
_.map(this.databases(category), _.bind(function (database,index) {
|
130
|
+
return (
|
131
|
+
<li className='list-group-item' key={'DB_'+category+index}>
|
132
|
+
{ this.renderDatabase(database) }
|
133
|
+
</li>
|
134
|
+
);
|
135
|
+
}, this))
|
136
|
+
}
|
137
|
+
</ul>
|
138
|
+
</div>
|
139
|
+
{
|
140
|
+
this.renderDatabaseTree(category)
|
141
|
+
}
|
142
|
+
</div>
|
143
|
+
);
|
144
|
+
},
|
145
|
+
|
146
|
+
renderDatabaseSearch: function (category) {
|
147
|
+
var tree_id = category + '_database_tree';
|
148
|
+
var search_id = tree_id + '_search';
|
149
|
+
|
150
|
+
return (
|
151
|
+
<input type='text' id={search_id} class='input'
|
152
|
+
onKeyUp=
|
153
|
+
{
|
154
|
+
_.bind(function () {
|
155
|
+
this.handleTreeSearch(category, tree_id, search_id);
|
156
|
+
}, this)
|
157
|
+
}
|
158
|
+
></input>
|
159
|
+
);
|
160
|
+
},
|
161
|
+
|
162
|
+
renderDatabaseTree: function (category) {
|
163
|
+
var tree_id = category + '_database_tree';
|
164
|
+
var data = this.props.tree[category];
|
165
|
+
|
166
|
+
return (
|
167
|
+
<div
|
168
|
+
id={tree_id}
|
169
|
+
className={'jstree_div'}
|
170
|
+
onClick=
|
171
|
+
{
|
172
|
+
_.bind(function () {
|
173
|
+
this.handleLoadTree(category);
|
174
|
+
}, this)
|
175
|
+
}
|
176
|
+
>
|
177
|
+
</div>
|
178
|
+
);
|
179
|
+
},
|
180
|
+
|
181
|
+
renderDatabase: function (database) {
|
182
|
+
var disabled = this.state.type && this.state.type !== database.type;
|
183
|
+
|
184
|
+
return (
|
185
|
+
<label
|
186
|
+
className={disabled && 'disabled database' || 'database'}>
|
187
|
+
<input
|
188
|
+
type='checkbox' name='databases[]' value={database.id}
|
189
|
+
data-type={database.type} disabled={disabled}
|
190
|
+
onChange=
|
191
|
+
{
|
192
|
+
_.bind(function () {
|
193
|
+
this.handleClick(database);
|
194
|
+
}, this)
|
195
|
+
}/>
|
196
|
+
{' ' + (database.title || database.name)}
|
197
|
+
</label>
|
198
|
+
);
|
199
|
+
},
|
200
|
+
|
201
|
+
componentDidUpdate: function () {
|
202
|
+
if (this.databases() && this.databases().length === 1) {
|
203
|
+
$('.databases').find('input').prop('checked',true);
|
204
|
+
this.handleClick(this.databases()[0]);
|
205
|
+
}
|
206
|
+
|
207
|
+
if (this.props.preSelectedDbs) {
|
208
|
+
var selectors = this.props.preSelectedDbs.map(db => `input[value=${db.id}]`);
|
209
|
+
$(...selectors).prop('checked',true);
|
210
|
+
this.handleClick(this.props.preSelectedDbs[0]);
|
211
|
+
this.props.preSelectedDbs = null;
|
212
|
+
}
|
213
|
+
this.props.onDatabaseTypeChanged(this.state.type);
|
214
|
+
}
|
215
|
+
});
|
data/public/js/download_fasta.js
CHANGED
data/public/js/hit.js
CHANGED
@@ -30,6 +30,10 @@ export default React.createClass({
|
|
30
30
|
return this.props.hit.length;
|
31
31
|
},
|
32
32
|
|
33
|
+
numHSPs: function () {
|
34
|
+
return this.props.hit.hsps.length;
|
35
|
+
},
|
36
|
+
|
33
37
|
// Internal helpers. //
|
34
38
|
|
35
39
|
/**
|
@@ -119,14 +123,14 @@ export default React.createClass({
|
|
119
123
|
{ this.hitLinks() }
|
120
124
|
<HSPOverview key={'kablammo' + this.props.query.id} query={this.props.query}
|
121
125
|
hit={this.props.hit} algorithm={this.props.algorithm}
|
122
|
-
showHSPCrumbs={this.
|
126
|
+
showHSPCrumbs={this.numHSPs() > 1 && this.numHSPs() < 27}
|
123
127
|
collapsed={this.props.veryBig} />
|
124
128
|
</div>;
|
125
129
|
},
|
126
130
|
|
127
131
|
hitLinks: function () {
|
128
132
|
var btns = [];
|
129
|
-
if (!this.props.imported_xml) {
|
133
|
+
if (!(this.props.imported_xml || this.props.non_parse_seqids)) {
|
130
134
|
btns = btns.concat([
|
131
135
|
this.viewSequenceButton(),
|
132
136
|
this.downloadFASTAButton()
|
data/public/js/hits_overview.js
CHANGED
@@ -9,7 +9,7 @@ import * as Helpers from './visualisation_helpers';
|
|
9
9
|
|
10
10
|
class Graph {
|
11
11
|
static name() {
|
12
|
-
return 'Length distribution of
|
12
|
+
return 'Length distribution of matching sequences';
|
13
13
|
}
|
14
14
|
|
15
15
|
static className() {
|
@@ -69,8 +69,7 @@ class Graph {
|
|
69
69
|
.range([0, this._width]);
|
70
70
|
this._bins = d3.layout.histogram()
|
71
71
|
.range(this._scale_x.domain())
|
72
|
-
.bins(this._scale_x.ticks(50))
|
73
|
-
(this._data);
|
72
|
+
.bins(this._scale_x.ticks(50))(this._data);
|
74
73
|
this._scale_y = d3.scale.linear()
|
75
74
|
.domain([0, d3.max(this._bins, function(d) { return d.length; })])
|
76
75
|
.range([this._height, 0]).nice();
|
@@ -129,14 +128,15 @@ class Graph {
|
|
129
128
|
bin.map(function (d,i) {
|
130
129
|
var y1 = bin.length - (i+1);
|
131
130
|
var len_index = _.findIndex(self.query.hits, {length: d});
|
131
|
+
var evalue = self.query.hits[len_index].hsps[0].evalue;
|
132
132
|
var item = {
|
133
133
|
value: d,
|
134
134
|
id: self.query.hits[len_index].id,
|
135
|
-
evalue:
|
135
|
+
evalue: evalue,
|
136
136
|
url: '#Query_'+self.query.number+'_hit_'+self.query.hits[len_index].number,
|
137
137
|
y0: y0,
|
138
138
|
y1: y0 += (y1 - y0),
|
139
|
-
color: Helpers.get_colors_for_evalue(
|
139
|
+
color: Helpers.get_colors_for_evalue(evalue,self.query.hits)
|
140
140
|
};
|
141
141
|
inner_data.push(item);
|
142
142
|
});
|
data/public/js/query.js
CHANGED
@@ -111,7 +111,7 @@ var HitsTable = React.createClass({
|
|
111
111
|
<div className="table-hit-overview">
|
112
112
|
<h4 className="caption" data-toggle="collapse" data-target={'#Query_'+this.props.query.number+'HT_'+this.props.query.number}>
|
113
113
|
<i className="fa fa-minus-square-o"></i>
|
114
|
-
<span>
|
114
|
+
<span>Sequences producing significant alignments</span>
|
115
115
|
</h4>
|
116
116
|
<div className="collapsed in"id={'Query_'+ this.props.query.number + 'HT_'+ this.props.query.number}>
|
117
117
|
<table
|
@@ -123,10 +123,7 @@ var HitsTable = React.createClass({
|
|
123
123
|
{!this.props.imported_xml && <th width="15%" className="text-right">Query coverage (%)</th>}
|
124
124
|
<th width="10%" className="text-right">Total score</th>
|
125
125
|
<th width="10%" className="text-right">E value</th>
|
126
|
-
<th width="10%" className="text-right"
|
127
|
-
data-placement="left" title="Total identity of all hsps / total length of all hsps">
|
128
|
-
Identity (%)
|
129
|
-
</th>
|
126
|
+
<th width="10%" className="text-right">Identity (%)</th>
|
130
127
|
</thead>
|
131
128
|
<tbody>
|
132
129
|
{
|
@@ -147,9 +144,9 @@ var HitsTable = React.createClass({
|
|
147
144
|
</td>
|
148
145
|
}
|
149
146
|
{!this.props.imported_xml && <td className="text-right">{hit.qcovs}</td>}
|
150
|
-
<td className="text-right">{hit.
|
147
|
+
<td className="text-right">{hit.total_score}</td>
|
151
148
|
<td className="text-right">{this.inExponential(hit.hsps[0].evalue)}</td>
|
152
|
-
<td className="text-right">{hit.identity}</td>
|
149
|
+
<td className="text-right">{this.inPercentage(hit.hsps[0].identity, hit.hsps[0].length)}</td>
|
153
150
|
</tr>
|
154
151
|
);
|
155
152
|
}, this))
|
data/public/js/report.js
CHANGED
@@ -203,6 +203,7 @@ var Report = React.createClass({
|
|
203
203
|
results.push(<Query key={'Query_'+query.number} query={query}
|
204
204
|
program={this.state.program} querydb={this.state.querydb}
|
205
205
|
showQueryCrumbs={this.state.queries.length > 1}
|
206
|
+
non_parse_seqids={this.state.non_parse_seqids}
|
206
207
|
imported_xml={this.state.imported_xml}
|
207
208
|
veryBig={this.state.veryBig} />);
|
208
209
|
}
|
@@ -216,6 +217,7 @@ var Report = React.createClass({
|
|
216
217
|
results.push(<Hit key={'Query_'+query.number+'_Hit_'+hit.number} query={query}
|
217
218
|
hit={hit} algorithm={this.state.program} querydb={this.state.querydb}
|
218
219
|
selectHit={this.selectHit} imported_xml={this.state.imported_xml}
|
220
|
+
non_parse_seqids={this.state.non_parse_seqids}
|
219
221
|
showQueryCrumbs={this.state.queries.length > 1}
|
220
222
|
showHitCrumbs={query.hits.length > 1}
|
221
223
|
veryBig={this.state.veryBig}
|
@@ -301,14 +303,12 @@ var Report = React.createClass({
|
|
301
303
|
resultsJSX: function () {
|
302
304
|
return (
|
303
305
|
<div className="row">
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
}
|
311
|
-
<div className={this.shouldShowSidebar() ? 'col-md-9' : 'col-md-12'}>
|
306
|
+
<div className="col-md-3 hidden-sm hidden-xs">
|
307
|
+
<Sidebar data={this.state}
|
308
|
+
atLeastOneHit={this.atLeastOneHit()}
|
309
|
+
shouldShowIndex={this.shouldShowIndex()} />
|
310
|
+
</div>
|
311
|
+
<div className="col-md-9">
|
312
312
|
{ this.overviewJSX() }
|
313
313
|
{ this.circosJSX() }
|
314
314
|
{ this.state.results }
|
@@ -387,17 +387,6 @@ var Report = React.createClass({
|
|
387
387
|
});
|
388
388
|
},
|
389
389
|
|
390
|
-
/**
|
391
|
-
* Returns true if sidebar should be shown.
|
392
|
-
*
|
393
|
-
* Sidebar is not shown if there is only one query and there are no hits
|
394
|
-
* corresponding to the query.
|
395
|
-
*/
|
396
|
-
shouldShowSidebar: function () {
|
397
|
-
return !(this.state.queries.length == 1 &&
|
398
|
-
this.state.queries[0].hits.length == 0);
|
399
|
-
},
|
400
|
-
|
401
390
|
/**
|
402
391
|
* Returns true if index should be shown in the sidebar. Index is shown
|
403
392
|
* only for 2 and 8 queries.
|
@@ -446,7 +435,7 @@ var Report = React.createClass({
|
|
446
435
|
*/
|
447
436
|
affixSidebar: function () {
|
448
437
|
var $sidebar = $('.sidebar');
|
449
|
-
var sidebarOffset = $sidebar.offset()
|
438
|
+
var sidebarOffset = $sidebar.offset();
|
450
439
|
if (sidebarOffset) {
|
451
440
|
$sidebar.affix({
|
452
441
|
offset: {
|
@@ -492,17 +481,16 @@ var Report = React.createClass({
|
|
492
481
|
$hit.next('.hsp').removeClass('glow');
|
493
482
|
}
|
494
483
|
|
484
|
+
var $a = $('.download-fasta-of-selected');
|
485
|
+
var $b = $('.download-alignment-of-selected');
|
486
|
+
|
495
487
|
if (num_checked >= 1)
|
496
488
|
{
|
497
|
-
var $a = $('.download-fasta-of-selected');
|
498
|
-
var $b = $('.download-alignment-of-selected');
|
499
489
|
$a.find('.text-bold').html(num_checked);
|
500
490
|
$b.find('.text-bold').html(num_checked);
|
501
491
|
}
|
502
492
|
|
503
493
|
if (num_checked == 0) {
|
504
|
-
var $a = $('.download-fasta-of-selected');
|
505
|
-
var $b = $('.download-alignment-of-selected');
|
506
494
|
$a.addClass('disabled').find('.text-bold').html('');
|
507
495
|
$b.addClass('disabled').find('.text-bold').html('');
|
508
496
|
}
|
data/public/js/search.js
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
import './jquery_world';
|
2
2
|
import React from 'react';
|
3
3
|
import _ from 'underscore';
|
4
|
+
import DatabasesTree from './databases_tree';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* Load necessary polyfills.
|
7
8
|
*/
|
9
|
+
$.webshims.setOptions('basePath', '/vendor/npm/webshim@1.15.8/js-webshim/minified/shims/');
|
8
10
|
$.webshims.polyfill('forms');
|
9
11
|
|
10
12
|
/**
|
@@ -206,7 +208,7 @@ var DnD = React.createClass({
|
|
206
208
|
var Form = React.createClass({
|
207
209
|
|
208
210
|
getInitialState: function () {
|
209
|
-
return { databases: {},
|
211
|
+
return { databases: [], preDefinedOpts: {}, tree: {} };
|
210
212
|
},
|
211
213
|
|
212
214
|
componentDidMount: function () {
|
@@ -225,6 +227,7 @@ var Form = React.createClass({
|
|
225
227
|
* advanced options.
|
226
228
|
*/
|
227
229
|
this.setState({
|
230
|
+
tree: data['tree'],
|
228
231
|
databases: data['database'],
|
229
232
|
preSelectedDbs: data['preSelectedDbs'],
|
230
233
|
preDefinedOpts: data['options']
|
@@ -236,6 +239,10 @@ var Form = React.createClass({
|
|
236
239
|
if (data['query']) {
|
237
240
|
this.refs.query.value(data['query']);
|
238
241
|
}
|
242
|
+
|
243
|
+
setTimeout(function(){
|
244
|
+
$('.jstree_div').click();
|
245
|
+
}, 1000);
|
239
246
|
}.bind(this));
|
240
247
|
|
241
248
|
/* Enable submitting form on Cmd+Enter */
|
@@ -248,6 +255,10 @@ var Form = React.createClass({
|
|
248
255
|
});
|
249
256
|
},
|
250
257
|
|
258
|
+
useTreeWidget: function () {
|
259
|
+
return !_.isEmpty(this.state.tree);
|
260
|
+
},
|
261
|
+
|
251
262
|
determineBlastMethod: function () {
|
252
263
|
var database_type = this.databaseType;
|
253
264
|
var sequence_type = this.sequenceType;
|
@@ -335,9 +346,16 @@ var Form = React.createClass({
|
|
335
346
|
<ProteinNotification/>
|
336
347
|
<MixedNotification/>
|
337
348
|
</div>
|
349
|
+
{this.useTreeWidget() ?
|
350
|
+
<DatabasesTree ref="databases"
|
351
|
+
databases={this.state.databases} tree={this.state.tree}
|
352
|
+
preSelectedDbs={this.state.preSelectedDbs}
|
353
|
+
onDatabaseTypeChanged={this.handleDatabaseTypeChanaged} />
|
354
|
+
:
|
338
355
|
<Databases ref="databases" databases={this.state.databases}
|
339
356
|
preSelectedDbs={this.state.preSelectedDbs}
|
340
357
|
onDatabaseTypeChanged={this.handleDatabaseTypeChanaged} />
|
358
|
+
}
|
341
359
|
<div className="form-group">
|
342
360
|
<Options ref="opts"/>
|
343
361
|
<div className="col-md-2">
|
@@ -687,6 +705,7 @@ var Databases = React.createClass({
|
|
687
705
|
$(`.${type} .database input:checked`).click();
|
688
706
|
break;
|
689
707
|
}
|
708
|
+
this.forceUpdate();
|
690
709
|
},
|
691
710
|
|
692
711
|
render: function () {
|
@@ -770,7 +789,7 @@ var Databases = React.createClass({
|
|
770
789
|
|
771
790
|
if (this.props.preSelectedDbs) {
|
772
791
|
var selectors = this.props.preSelectedDbs.map(db => `input[value=${db.id}]`);
|
773
|
-
$(
|
792
|
+
$(selectors.join(',')).prop('checked',true);
|
774
793
|
this.handleClick(this.props.preSelectedDbs[0]);
|
775
794
|
this.props.preSelectedDbs = null;
|
776
795
|
}
|
data/public/js/sidebar.js
CHANGED
@@ -166,15 +166,15 @@ export default React.createClass({
|
|
166
166
|
</div>
|
167
167
|
<ul className="nav">
|
168
168
|
{
|
169
|
-
!this.props.data.imported_xml && <li>
|
170
|
-
<a href="#" className=
|
169
|
+
!(this.props.data.imported_xml || this.props.data.non_parse_seqids) && <li>
|
170
|
+
<a href="#" className={`btn-link download-fasta-of-all ${!this.props.atLeastOneHit && 'disabled'}`}
|
171
171
|
onClick={this.downloadFastaOfAll}>
|
172
172
|
FASTA of all hits
|
173
173
|
</a>
|
174
174
|
</li>
|
175
175
|
}
|
176
176
|
{
|
177
|
-
!this.props.data.imported_xml && <li>
|
177
|
+
!(this.props.data.imported_xml || this.props.data.non_parse_seqids) && <li>
|
178
178
|
<a href="#" className="btn-link download-fasta-of-selected disabled"
|
179
179
|
onClick={this.downloadFastaOfSelected}>
|
180
180
|
FASTA of <span className="text-bold"></span> selected hit(s)
|
@@ -182,7 +182,7 @@ export default React.createClass({
|
|
182
182
|
</li>
|
183
183
|
}
|
184
184
|
<li>
|
185
|
-
<a href="#" className=
|
185
|
+
<a href="#" className={`btn-link download-alignment-of-all ${!this.props.atLeastOneHit && 'disabled'}`}
|
186
186
|
onClick={this.downloadAlignmentOfAll}>
|
187
187
|
Alignment of all hits
|
188
188
|
</a>
|
data/public/js/svgExporter.js
CHANGED
@@ -16,7 +16,7 @@ var export_as_svg = function (svg, filename) {
|
|
16
16
|
var blob = new Blob([serialize_svg(svg)], { type: 'text/xml' });
|
17
17
|
filename = Exporter.sanitize_filename(filename) + '.svg';
|
18
18
|
Exporter.download_blob(blob, filename);
|
19
|
-
}
|
19
|
+
};
|
20
20
|
|
21
21
|
/**
|
22
22
|
* Exports the given <svg> DOM node as a .png file.
|
@@ -45,19 +45,19 @@ var export_as_png = function (svg, filename) {
|
|
45
45
|
};
|
46
46
|
|
47
47
|
img.src = 'data:image/svg+xml;base64,' + window.btoa(serialize_svg(svg));
|
48
|
-
}
|
48
|
+
};
|
49
49
|
|
50
50
|
var serialize_svg = function(svg) {
|
51
51
|
// Clone svg first so that none of our changes to affect the actual SVG.
|
52
52
|
svg = svg.cloneNode(true);
|
53
53
|
|
54
54
|
d3.select(svg).attr('version', '1.1')
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
.insert('defs', ':first-child')
|
56
|
+
.append('style')
|
57
|
+
.attr('class', 'exported-css')
|
58
|
+
.attr('type', 'text/css')
|
59
|
+
.node()
|
60
|
+
.textContent = get_styles();
|
61
61
|
|
62
62
|
svg.removeAttribute('xmlns');
|
63
63
|
svg.removeAttribute('xlink');
|
@@ -67,8 +67,8 @@ var serialize_svg = function(svg) {
|
|
67
67
|
var source = (new XMLSerializer()).serializeToString(svg);
|
68
68
|
var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC ' +
|
69
69
|
'"-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
|
70
|
-
|
71
|
-
}
|
70
|
+
return doctype + source;
|
71
|
+
};
|
72
72
|
|
73
73
|
var get_styles = function () {
|
74
74
|
var styles = '';
|
@@ -113,14 +113,14 @@ var get_styles = function () {
|
|
113
113
|
}
|
114
114
|
|
115
115
|
return styles;
|
116
|
-
}
|
116
|
+
};
|
117
117
|
|
118
118
|
var handle_click = function (export_callback) {
|
119
119
|
return function () {
|
120
120
|
var $svg = $(this).parents('.grapher').find('svg');
|
121
121
|
export_callback($svg[0], $svg.attr('data-name'));
|
122
122
|
return false;
|
123
|
-
}
|
123
|
+
};
|
124
124
|
};
|
125
125
|
|
126
126
|
var $body = $('body');
|
@@ -39,16 +39,15 @@ export function tick_formatter(scale, seq_type) {
|
|
39
39
|
var digits = 0;
|
40
40
|
var format;
|
41
41
|
var _ticks;
|
42
|
-
|
42
|
+
|
43
|
+
do {
|
43
44
|
format = d3.format('.' + digits + 'f');
|
44
45
|
_ticks = scale.ticks().map(function (d) {
|
45
46
|
return format(prefix.scale(d));
|
46
47
|
});
|
47
|
-
if (_ticks.length === _.uniq(_ticks).length) {
|
48
|
-
break;
|
49
|
-
}
|
50
48
|
digits++;
|
51
|
-
|
49
|
+
|
50
|
+
} while (_ticks.length !== _.uniq(_ticks).length);
|
52
51
|
|
53
52
|
return function (d) {
|
54
53
|
if (!prefix.symbol || d === scale.domain()[0]) {
|