sequenceserver 2.0.0.beta4 → 2.0.0.rc5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.dockerignore +1 -0
- data/.travis.yml +7 -4
- data/AppImage/sequenceserver.sh +5 -0
- data/Dockerfile +14 -12
- data/bin/sequenceserver +37 -28
- data/lib/sequenceserver.rb +35 -7
- data/lib/sequenceserver/blast/job.rb +18 -25
- data/lib/sequenceserver/blast/report.rb +68 -34
- data/lib/sequenceserver/config.rb +1 -1
- data/lib/sequenceserver/database.rb +0 -129
- data/lib/sequenceserver/makeblastdb.rb +243 -0
- data/lib/sequenceserver/routes.rb +28 -2
- data/lib/sequenceserver/version.rb +1 -1
- data/public/SequenceServer_logo.png +0 -0
- data/public/css/grapher.css +8 -15
- data/public/css/sequenceserver.css +119 -55
- data/public/css/sequenceserver.min.css +3 -3
- data/public/js/circos.js +1 -1
- data/public/js/download_fasta.js +17 -0
- data/public/js/grapher.js +7 -9
- data/public/js/hit.js +217 -0
- data/public/js/hits_overview.js +12 -13
- data/public/js/hsp.js +104 -84
- data/public/js/{sequenceserver.js → jquery_world.js} +1 -18
- data/public/js/kablammo.js +337 -334
- data/public/js/length_distribution.js +1 -1
- data/public/js/query.js +147 -0
- data/public/js/report.js +216 -836
- data/public/js/search.js +194 -192
- data/public/js/sequence_modal.js +167 -0
- data/public/js/sidebar.js +210 -0
- data/public/js/utils.js +2 -19
- data/public/js/visualisation_helpers.js +2 -2
- data/public/sequenceserver-report.min.js +19 -19
- data/public/sequenceserver-search.min.js +11 -11
- data/public/vendor/github/twbs/bootstrap@3.3.5/js/bootstrap.js +2 -2
- data/spec/blast_versions/blast_2.2.30/import_spec_capybara_local_2.2.30.rb +15 -15
- data/spec/blast_versions/blast_2.2.31/import_spec_capybara_local_2.2.31.rb +15 -15
- data/spec/blast_versions/blast_2.3.0/import_spec_capybara_local_2.3.0.rb +15 -15
- data/spec/blast_versions/blast_2.4.0/import_spec_capybara_local_2.4.0.rb +15 -15
- data/spec/blast_versions/blast_2.5.0/import_spec_capybara_local_2.5.0.rb +15 -15
- data/spec/blast_versions/blast_2.6.0/import_spec_capybara_local_2.6.0.rb +15 -15
- data/spec/blast_versions/blast_2.7.1/import_spec_capybara_local_2.7.1.rb +15 -15
- data/spec/blast_versions/blast_2.8.1/import_spec_capybara_local_2.8.1.rb +15 -15
- data/spec/blast_versions/blast_2.9.0/import_spec_capybara_local_2.9.0.rb +15 -15
- data/spec/blast_versions/diamond_0.9.24/import_spec_capybara_local_0.9.24.rb +6 -6
- data/spec/capybara_spec.rb +14 -3
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.ndb +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhr +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nin +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nos +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.not +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.ntf +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nto +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pdb +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.phr +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pin +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pos +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pot +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.ptf +0 -0
- data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pto +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pdb +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phr +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pin +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pos +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pot +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.ptf +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pto +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.ndb +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nhr +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nin +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nos +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.not +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsq +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.ntf +0 -0
- data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nto +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhd +8 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhi +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhr +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nin +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nog +0 -0
- data/spec/database/{sample → v4}/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsd +0 -0
- data/spec/database/{sample → v4}/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsi +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsq +0 -0
- data/spec/database/v4/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.txt +8 -0
- data/spec/database/v4/links.rb +23 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta +6449 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.phd +1189 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.phi +0 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.phr +0 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pin +0 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pog +0 -0
- data/spec/database/{sample → v4}/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psd +0 -0
- data/spec/database/{sample → v4}/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psi +0 -0
- data/spec/database/v4/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psq +0 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phd +9140 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phi +0 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phr +0 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pin +0 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.pog +0 -0
- data/spec/database/{sample → v4}/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psd +0 -0
- data/spec/database/{sample → v4}/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psi +0 -0
- data/spec/database/v4/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psq +0 -0
- data/spec/database/v4/proteins/uniprot/URL +1 -0
- data/spec/database/v4/si_uniprot_idmap.yml +14180 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta +5486 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nhd +473 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nhi +0 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nhr +0 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nin +0 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nog +0 -0
- data/spec/database/{sample → v4}/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsd +0 -0
- data/spec/database/{sample → v4}/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsi +0 -0
- data/spec/database/v4/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsq +0 -0
- data/spec/database_spec.rb +0 -76
- data/spec/makeblastdb_spec.rb +121 -0
- data/views/layout.erb +5 -1
- metadata +75 -15
data/public/js/hit.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import _ from 'underscore';
|
|
3
|
+
|
|
4
|
+
import HSPOverview from './kablammo';
|
|
5
|
+
import downloadFASTA from './download_fasta';
|
|
6
|
+
import AlignmentExporter from './alignment_exporter'; // to download textual alignment
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Component for each hit. Receives props from Report. Has no state.
|
|
10
|
+
*/
|
|
11
|
+
export default React.createClass({
|
|
12
|
+
/**
|
|
13
|
+
* Returns accession number of the hit sequence.
|
|
14
|
+
*/
|
|
15
|
+
accession: function () {
|
|
16
|
+
return this.props.hit.accession;
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns length of the hit sequence.
|
|
21
|
+
*/
|
|
22
|
+
hitLength: function () {
|
|
23
|
+
return this.props.hit.length;
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Internal helpers. //
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns id that will be used for the DOM node corresponding to the hit.
|
|
30
|
+
*/
|
|
31
|
+
domID: function () {
|
|
32
|
+
return 'Query_' + this.props.query.number + '_hit_' + this.props.hit.number;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
databaseIDs: function () {
|
|
36
|
+
return _.map(this.props.querydb, _.iteratee('id'));
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
showSequenceViewer: function () {
|
|
40
|
+
this.props.showSequenceModal(this.viewSequenceLink());
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
viewSequenceLink: function () {
|
|
44
|
+
return encodeURI(`get_sequence/?sequence_ids=${this.accession()}&database_ids=${this.databaseIDs()}`);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
downloadFASTA: function (event) {
|
|
48
|
+
var accessions = [this.accession()];
|
|
49
|
+
downloadFASTA(accessions, this.databaseIDs());
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Event-handler for exporting alignments.
|
|
53
|
+
// Calls relevant method on AlignmentExporter defined in alignment_exporter.js.
|
|
54
|
+
downloadAlignment: function (event) {
|
|
55
|
+
var hsps = _.map(this.props.hit.hsps, _.bind(function (hsp) {
|
|
56
|
+
hsp.query_id = this.props.query.id;
|
|
57
|
+
hsp.hit_id = this.props.hit.id;
|
|
58
|
+
return hsp;
|
|
59
|
+
}, this));
|
|
60
|
+
|
|
61
|
+
var aln_exporter = new AlignmentExporter();
|
|
62
|
+
aln_exporter.export_alignments(hsps, this.props.query.id+'_'+this.props.hit.id);
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// Life cycle methods //
|
|
67
|
+
|
|
68
|
+
render: function () {
|
|
69
|
+
return (
|
|
70
|
+
<div className="hit" id={this.domID()} data-hit-def={this.props.hit.id}
|
|
71
|
+
data-hit-len={this.props.hit.length} data-hit-evalue={this.props.hit.evalue}>
|
|
72
|
+
{ this.headerJSX() } { this.contentJSX() }
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// See Query.shouldComponentUpdate. The same applies for hits.
|
|
78
|
+
shouldComponentUpdate: function () {
|
|
79
|
+
return !this.props.hit;
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
headerJSX: function () {
|
|
83
|
+
var meta = `length: ${this.hitLength().toLocaleString()}`;
|
|
84
|
+
|
|
85
|
+
if (this.props.showQueryCrumbs && this.props.showHitCrumbs) {
|
|
86
|
+
// Multiper queries, multiple hits
|
|
87
|
+
meta = `hit ${this.props.hit.number} of query ${this.props.query.number}, ` + meta;
|
|
88
|
+
}
|
|
89
|
+
else if (this.props.showQueryCrumbs && !this.props.showHitCrumbs) {
|
|
90
|
+
// Multiple queries, single hit
|
|
91
|
+
meta = `the only hit of query ${this.props.query.number}, ` + meta;
|
|
92
|
+
}
|
|
93
|
+
else if (!this.props.showQueryCrumbs && this.props.showHitCrumbs) {
|
|
94
|
+
// Single query, multiple hits
|
|
95
|
+
meta = `hit ${this.props.hit.number}, ` + meta;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return <div className="section-header">
|
|
99
|
+
<h4>
|
|
100
|
+
<i className="fa fa-minus-square-o"></i>
|
|
101
|
+
<strong>{this.props.hit.id}</strong>
|
|
102
|
+
{this.props.hit.title}
|
|
103
|
+
</h4>
|
|
104
|
+
<span className="label label-reset pos-label">{meta}</span>
|
|
105
|
+
</div>;
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
contentJSX: function () {
|
|
109
|
+
return <div className="section-content" data-parent-hit={this.domID()}>
|
|
110
|
+
{ this.hitLinks() }
|
|
111
|
+
<HSPOverview key={'kablammo' + this.props.query.id} query={this.props.query}
|
|
112
|
+
hit={this.props.hit} algorithm={this.props.algorithm}
|
|
113
|
+
showHSPCrumbs={this.props.hit.hsps.length > 1}
|
|
114
|
+
collapsed={this.props.veryBig} />
|
|
115
|
+
</div>;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
hitLinks: function () {
|
|
119
|
+
var btns = [];
|
|
120
|
+
if (!this.props.imported_xml) {
|
|
121
|
+
btns = btns.concat([
|
|
122
|
+
this.viewSequenceButton(),
|
|
123
|
+
this.downloadFASTAButton()
|
|
124
|
+
]);
|
|
125
|
+
}
|
|
126
|
+
btns.push(this.downloadAlignmentButton());
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div className="hit-links">
|
|
130
|
+
<label>
|
|
131
|
+
<input type="checkbox" id={this.domID() + '_checkbox'}
|
|
132
|
+
value={this.accession()} onChange={function () {
|
|
133
|
+
this.props.selectHit(this.domID() + '_checkbox');
|
|
134
|
+
}.bind(this)} data-target={'#' + this.domID()}
|
|
135
|
+
/> Select
|
|
136
|
+
</label>
|
|
137
|
+
{
|
|
138
|
+
btns.map((btn) => {
|
|
139
|
+
return [<span className="line">|</span>, this.button(btn)];
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
{
|
|
143
|
+
this.props.hit.links.map((link) => {
|
|
144
|
+
return [<span className="line">|</span>, this.a(link)];
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Return JSX for view sequence button.
|
|
152
|
+
viewSequenceButton: function () {
|
|
153
|
+
if (this.hitLength() > 10000) {
|
|
154
|
+
return {
|
|
155
|
+
text: 'Sequence',
|
|
156
|
+
icon: 'fa-eye',
|
|
157
|
+
className: 'view-sequence',
|
|
158
|
+
title: 'Sequence too long',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return {
|
|
163
|
+
text: 'Sequence',
|
|
164
|
+
icon: 'fa-eye',
|
|
165
|
+
className: 'view-sequence',
|
|
166
|
+
onClick: () => this.showSequenceViewer()
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
downloadFASTAButton: function () {
|
|
173
|
+
return {
|
|
174
|
+
text: 'FASTA',
|
|
175
|
+
icon: 'fa-download',
|
|
176
|
+
className: 'download-fa',
|
|
177
|
+
onClick: () => this.downloadFASTA()
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
downloadAlignmentButton: function () {
|
|
182
|
+
return {
|
|
183
|
+
text: 'Alignment',
|
|
184
|
+
icon: 'fa-download',
|
|
185
|
+
className: 'download-aln',
|
|
186
|
+
onClick: () => this.downloadAlignment()
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
button: function ({text, icon, title, className, onClick}) {
|
|
191
|
+
if (onClick) {
|
|
192
|
+
return <button className={`btn-link ${className}`}
|
|
193
|
+
title={title} onClick={onClick}><i className={`fa ${icon}`}></i> {text}
|
|
194
|
+
</button>;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
return <button className="btn-link view-sequence disabled"
|
|
198
|
+
title={title} disabled="true">
|
|
199
|
+
<i className={`fa ${icon}`}></i> {text}
|
|
200
|
+
</button>;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Render URL for sequence-viewer.
|
|
206
|
+
*/
|
|
207
|
+
a: function (link) {
|
|
208
|
+
if (!link.title || !link.url) return;
|
|
209
|
+
|
|
210
|
+
let className = 'btn btn-link';
|
|
211
|
+
if (link.class) className = `${className} ${link.class}`;
|
|
212
|
+
return <a href={link.url} className={className} target='_blank'>
|
|
213
|
+
{link.icon && <i className={'fa ' + link.icon}></i>}
|
|
214
|
+
{' ' + link.title + ' '}
|
|
215
|
+
</a>;
|
|
216
|
+
}
|
|
217
|
+
});
|
data/public/js/hits_overview.js
CHANGED
|
@@ -166,10 +166,10 @@ class Graph {
|
|
|
166
166
|
drawLegend(svg, options, width, height, hits) {
|
|
167
167
|
var svg_legend = svg.append('g')
|
|
168
168
|
.attr('transform',
|
|
169
|
-
'translate(0,' + (height - 1.
|
|
169
|
+
'translate(0,' + (height - 1.75 * options.margin) + ')');
|
|
170
170
|
|
|
171
171
|
svg_legend.append('rect')
|
|
172
|
-
.attr('x', 7 * (width - 2 * options.margin) / 10)
|
|
172
|
+
.attr('x', 7.5 * (width - 2 * options.margin) / 10)
|
|
173
173
|
.attr('width', 2 * (width - 4 * options.margin) / 10)
|
|
174
174
|
.attr('height', options.legend)
|
|
175
175
|
.attr('fill', 'url(#legend-grad)');
|
|
@@ -177,7 +177,7 @@ class Graph {
|
|
|
177
177
|
svg_legend.append('text')
|
|
178
178
|
.attr('class',' legend-text')
|
|
179
179
|
.attr('transform', 'translate(0, ' +options.legend +')')
|
|
180
|
-
.attr('x',
|
|
180
|
+
.attr('x', 9.5 * (width - 2 * options.margin) / 10 + options.margin / 2)
|
|
181
181
|
.text('Weaker hits');
|
|
182
182
|
// .text(function() {
|
|
183
183
|
// return Helpers.prettify_evalue(hits[hits.length-1].hitEvalue);
|
|
@@ -186,7 +186,7 @@ class Graph {
|
|
|
186
186
|
svg_legend.append('text')
|
|
187
187
|
.attr('class',' legend-text')
|
|
188
188
|
.attr('transform', 'translate(0, ' + options.legend + ')')
|
|
189
|
-
.attr('x',
|
|
189
|
+
.attr('x', 6.7 * (width - 2 * options.margin) / 10 - options.margin / 2)
|
|
190
190
|
.text('Stronger hits');
|
|
191
191
|
// .text(function () {
|
|
192
192
|
// return Helpers.prettify_evalue(hits[0].hitEvalue);
|
|
@@ -196,9 +196,9 @@ class Graph {
|
|
|
196
196
|
.attr('id', 'legend-grad')
|
|
197
197
|
.selectAll('stop')
|
|
198
198
|
.data([
|
|
199
|
-
{offset: '0%', color: '#
|
|
200
|
-
{offset: '
|
|
201
|
-
{offset: '100%', color: '#
|
|
199
|
+
{offset: '0%', color: '#000'},
|
|
200
|
+
{offset: '45%', color: '#c74f14'},
|
|
201
|
+
{offset: '100%', color: '#f6bea2'}
|
|
202
202
|
])
|
|
203
203
|
.enter()
|
|
204
204
|
.append('stop')
|
|
@@ -216,7 +216,7 @@ class Graph {
|
|
|
216
216
|
* margin: Margin around the svg element.
|
|
217
217
|
*/
|
|
218
218
|
var defaults = {
|
|
219
|
-
barHeight:
|
|
219
|
+
barHeight: 4,
|
|
220
220
|
legend: inhits.length > 1 ? 3 : 0,
|
|
221
221
|
margin: 20
|
|
222
222
|
},
|
|
@@ -237,7 +237,8 @@ class Graph {
|
|
|
237
237
|
|
|
238
238
|
var width = $graphDiv.width();
|
|
239
239
|
var height = hits.length * (options.barHeight) +
|
|
240
|
-
|
|
240
|
+
2 * options.legend + 4 * options.margin;
|
|
241
|
+
|
|
241
242
|
// var height = $graphDiv.height();
|
|
242
243
|
|
|
243
244
|
var SEQ_TYPES = {
|
|
@@ -310,7 +311,7 @@ class Graph {
|
|
|
310
311
|
return d.hitEvalue;
|
|
311
312
|
}))
|
|
312
313
|
])
|
|
313
|
-
.range([
|
|
314
|
+
.range([0,0.8]);
|
|
314
315
|
|
|
315
316
|
svg.append('g')
|
|
316
317
|
.attr('class', 'ghit')
|
|
@@ -330,9 +331,7 @@ class Graph {
|
|
|
330
331
|
// Drawing the HSPs connector line using the same
|
|
331
332
|
// color as that of the hit track (using lookahead).
|
|
332
333
|
var yHspline = y(d.hitId) + options.barHeight / 2;
|
|
333
|
-
var hsplineColor = d3.
|
|
334
|
-
gradScale(v.hspEvalue),
|
|
335
|
-
gradScale(v.hspEvalue));
|
|
334
|
+
var hsplineColor = d3.hsl(20, 0.82, gradScale(v.hspEvalue));
|
|
336
335
|
|
|
337
336
|
if (j+1 < d.length) {
|
|
338
337
|
if (d[j].hspEnd <= d[j+1].hspStart) {
|
data/public/js/hsp.js
CHANGED
|
@@ -17,16 +17,22 @@ export default class HSP extends React.Component {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
domID() {
|
|
20
|
-
return
|
|
21
|
-
this.props.
|
|
20
|
+
return 'Query_' + this.props.query.number + '_hit_' +
|
|
21
|
+
this.props.hit.number + '_' + this.props.hsp.number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
hitDOM_ID() {
|
|
25
|
+
return 'Query_' + this.props.query.number + '_hit_' + this.props.hit.number;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
// Renders pretty formatted alignment.
|
|
25
29
|
render () {
|
|
26
30
|
return (
|
|
27
|
-
<div className="hsp" id={this.domID()} ref="hsp"
|
|
31
|
+
<div className="hsp" id={this.domID()} ref="hsp"
|
|
32
|
+
data-parent-hit={this.hitDOM_ID()}>
|
|
28
33
|
<pre className="pre-reset hsp-stats">
|
|
29
|
-
{Helpers.toLetters(this.hsp.number)
|
|
34
|
+
{this.props.showHSPNumbers && `${Helpers.toLetters(this.hsp.number)}. `}
|
|
35
|
+
{this.hspStats().map((s, i) => <span key={i}>{s}</span>)}
|
|
30
36
|
</pre>
|
|
31
37
|
{this.hspLines()}
|
|
32
38
|
</div>
|
|
@@ -39,11 +45,17 @@ export default class HSP extends React.Component {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
draw () {
|
|
42
|
-
var
|
|
43
|
-
|
|
48
|
+
var charWidth = this.props.getCharacterWidth();
|
|
49
|
+
var containerWidth = $(React.findDOMNode(this.refs.hsp)).width();
|
|
50
|
+
this.chars = Math.floor((containerWidth - 4) / charWidth);
|
|
44
51
|
this.forceUpdate();
|
|
45
52
|
}
|
|
46
53
|
|
|
54
|
+
// See Query.shouldComponentUpdate. The same applies for hsp.
|
|
55
|
+
shouldComponentUpdate () {
|
|
56
|
+
return !this.props.hsp;
|
|
57
|
+
}
|
|
58
|
+
|
|
47
59
|
/**
|
|
48
60
|
* Returns an array of span elements or plain strings (React automatically
|
|
49
61
|
* adds span tag around strings). This array is passed as it is to JSX to be
|
|
@@ -60,17 +72,17 @@ export default class HSP extends React.Component {
|
|
|
60
72
|
line.push(`Score: ${Utils.inTwoDecimal(this.hsp.bit_score)} (${this.hsp.score}), `);
|
|
61
73
|
|
|
62
74
|
// E value
|
|
63
|
-
line.push(
|
|
75
|
+
line.push('E value: '); line.push(Utils.inExponential(this.hsp.evalue)); line.push(', ');
|
|
64
76
|
|
|
65
77
|
// Identity
|
|
66
|
-
line.push([`
|
|
78
|
+
line.push([`Identity: ${Utils.inFraction(this.hsp.identity, this.hsp.length)} (${Utils.inPercentage(this.hsp.identity, this.hsp.length)}), `]);
|
|
67
79
|
|
|
68
80
|
// Positives (for protein alignment).
|
|
69
81
|
if (this.props.algorithm === 'blastp' ||
|
|
70
82
|
this.props.algorithm === 'blastx' ||
|
|
71
83
|
this.props.algorithm === 'tblastn' ||
|
|
72
84
|
this.props.algorithm === 'tblastx') {
|
|
73
|
-
line.push(`Positives: ${Utils.inFraction(this.hsp.positives, this.hsp.length)} (${Utils.inPercentage(this.hsp.positives, this.hsp.length)}), `)
|
|
85
|
+
line.push(`Positives: ${Utils.inFraction(this.hsp.positives, this.hsp.length)} (${Utils.inPercentage(this.hsp.positives, this.hsp.length)}), `);
|
|
74
86
|
}
|
|
75
87
|
|
|
76
88
|
// Gaps
|
|
@@ -80,23 +92,27 @@ export default class HSP extends React.Component {
|
|
|
80
92
|
//line.push(`Query coverage: ${this.hsp.qcovhsp}%, `)
|
|
81
93
|
|
|
82
94
|
switch (this.props.algorithm) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
case 'tblastx':
|
|
96
|
+
line.push(`, Frame: ${Utils.inFraction(this.hsp.qframe, this.hsp.sframe)}`);
|
|
97
|
+
break;
|
|
98
|
+
case 'blastn':
|
|
99
|
+
line.push(`, Strand: ${(this.hsp.qframe > 0 ? '+' : '-')} / ${(this.hsp.sframe > 0 ? '+' : '-')}`);
|
|
100
|
+
break;
|
|
101
|
+
case 'blastx':
|
|
102
|
+
line.push(`, Query Frame: ${this.hsp.qframe}`);
|
|
103
|
+
break;
|
|
104
|
+
case 'tblastn':
|
|
105
|
+
line.push(`, Hit Frame: ${this.hsp.sframe}`);
|
|
106
|
+
break;
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
return line;
|
|
98
110
|
}
|
|
99
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Returns array of pre tags containing the three query, middle, and subject
|
|
114
|
+
* lines that together comprise one 'rendered line' of HSP.
|
|
115
|
+
*/
|
|
100
116
|
hspLines () {
|
|
101
117
|
// Space reserved for showing coordinates
|
|
102
118
|
var width = this.width();
|
|
@@ -115,7 +131,6 @@ export default class HSP extends React.Component {
|
|
|
115
131
|
var nqseq = this.nqseq();
|
|
116
132
|
var nsseq = this.nsseq();
|
|
117
133
|
for (let i = 1; i <= lines; i++) {
|
|
118
|
-
let line = [];
|
|
119
134
|
let seq_start_index = chars * (i - 1);
|
|
120
135
|
let seq_stop_index = seq_start_index + chars;
|
|
121
136
|
|
|
@@ -133,32 +148,37 @@ export default class HSP extends React.Component {
|
|
|
133
148
|
this.sframe_unit() * this.sframe_sign();
|
|
134
149
|
nsseq = lsend + this.sframe_unit() * this.sframe_sign();
|
|
135
150
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
pp.push(
|
|
152
|
+
<pre key={this.hsp.number + ',' + i} className="pre-reset hsp-lines">
|
|
153
|
+
<span className="hsp-coords">
|
|
154
|
+
{`Query ${this.formatCoords(lqstart, width)} `}
|
|
155
|
+
</span>
|
|
156
|
+
<span>{lqseq}</span>
|
|
157
|
+
<span className="hsp-coords">{` ${lqend}`}</span>
|
|
158
|
+
<br/>
|
|
159
|
+
<span className="hsp-coords">
|
|
160
|
+
{`${this.formatCoords('', width + 8)} `}
|
|
161
|
+
</span>
|
|
162
|
+
<span>{lmseq}</span>
|
|
163
|
+
<br/>
|
|
164
|
+
<span className="hsp-coords">
|
|
165
|
+
{`Subject ${this.formatCoords(lsstart, width)} `}
|
|
166
|
+
</span>
|
|
167
|
+
<span>{lsseq}</span>
|
|
168
|
+
<span className="hsp-coords">{` ${lsend}`}</span>
|
|
169
|
+
<br/>
|
|
170
|
+
</pre>);
|
|
152
171
|
}
|
|
153
172
|
|
|
154
173
|
return pp;
|
|
155
174
|
}
|
|
156
175
|
|
|
157
|
-
// Width of
|
|
158
|
-
|
|
176
|
+
// Width of the coordinate part of hsp lines. Essentially the length of
|
|
177
|
+
// the largest coordinate.
|
|
178
|
+
width () {
|
|
159
179
|
return _.max(_.map([this.hsp.qstart, this.hsp.qend,
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
this.hsp.sstart, this.hsp.send],
|
|
181
|
+
(n) => { return n.toString().length; }));
|
|
162
182
|
}
|
|
163
183
|
|
|
164
184
|
// Alignment start coordinate for query sequence.
|
|
@@ -167,16 +187,16 @@ export default class HSP extends React.Component {
|
|
|
167
187
|
// (translated) query sequence aligned.
|
|
168
188
|
nqseq () {
|
|
169
189
|
switch (this.props.algorithm) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
case 'blastp':
|
|
191
|
+
case 'blastx':
|
|
192
|
+
case 'tblastn':
|
|
193
|
+
case 'tblastx':
|
|
194
|
+
return this.hsp.qframe >= 0 ? this.hsp.qstart : this.hsp.qend;
|
|
195
|
+
case 'blastn':
|
|
196
|
+
// BLASTN is a bit weird in that, no matter which direction the query
|
|
197
|
+
// sequence aligned in, qstart is taken as alignment start coordinate
|
|
198
|
+
// for query.
|
|
199
|
+
return this.hsp.qstart;
|
|
180
200
|
}
|
|
181
201
|
}
|
|
182
202
|
|
|
@@ -186,16 +206,16 @@ export default class HSP extends React.Component {
|
|
|
186
206
|
// (translated) subject sequence aligned.
|
|
187
207
|
nsseq () {
|
|
188
208
|
switch (this.props.algorithm) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
209
|
+
case 'blastp':
|
|
210
|
+
case 'blastx':
|
|
211
|
+
case 'tblastn':
|
|
212
|
+
case 'tblastx':
|
|
213
|
+
return this.hsp.sframe >= 0 ? this.hsp.sstart : this.hsp.send;
|
|
214
|
+
case 'blastn':
|
|
215
|
+
// BLASTN is a bit weird in that, no matter which direction the
|
|
216
|
+
// subject sequence aligned in, sstart is taken as alignment
|
|
217
|
+
// start coordinate for subject.
|
|
218
|
+
return this.hsp.sstart;
|
|
199
219
|
}
|
|
200
220
|
}
|
|
201
221
|
|
|
@@ -209,16 +229,16 @@ export default class HSP extends React.Component {
|
|
|
209
229
|
// translated or not.
|
|
210
230
|
qframe_unit () {
|
|
211
231
|
switch (this.props.algorithm) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
case 'blastp':
|
|
233
|
+
case 'blastn':
|
|
234
|
+
case 'tblastn':
|
|
235
|
+
return 1;
|
|
236
|
+
case 'blastx':
|
|
237
|
+
// _Translated_ nucleotide query against protein database.
|
|
238
|
+
case 'tblastx':
|
|
239
|
+
// _Translated_ nucleotide query against translated
|
|
240
|
+
// nucleotide database.
|
|
241
|
+
return 3;
|
|
222
242
|
}
|
|
223
243
|
}
|
|
224
244
|
|
|
@@ -232,17 +252,17 @@ export default class HSP extends React.Component {
|
|
|
232
252
|
// translated or not.
|
|
233
253
|
sframe_unit () {
|
|
234
254
|
switch (this.props.algorithm) {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
255
|
+
case 'blastp':
|
|
256
|
+
case 'blastx':
|
|
257
|
+
case 'blastn':
|
|
258
|
+
return 1;
|
|
259
|
+
case 'tblastn':
|
|
260
|
+
// Protein query against _translated_ nucleotide database.
|
|
261
|
+
return 3;
|
|
262
|
+
case 'tblastx':
|
|
263
|
+
// Translated nucleotide query against _translated_
|
|
264
|
+
// nucleotide database.
|
|
265
|
+
return 3;
|
|
246
266
|
}
|
|
247
267
|
}
|
|
248
268
|
|
|
@@ -283,7 +303,7 @@ export default class HSP extends React.Component {
|
|
|
283
303
|
}
|
|
284
304
|
|
|
285
305
|
spanCoords (text) {
|
|
286
|
-
return <span className="hsp-coords">{text}</span
|
|
306
|
+
return <span className="hsp-coords">{text}</span>;
|
|
287
307
|
}
|
|
288
308
|
}
|
|
289
309
|
|