sequenceserver 3.1.2 → 3.2.0
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 +4 -4
- data/lib/sequenceserver/api_errors.rb +18 -0
- data/lib/sequenceserver/blast/hit.rb +1 -2
- data/lib/sequenceserver/blast/job.rb +15 -5
- data/lib/sequenceserver/blast/report.rb +5 -1
- data/lib/sequenceserver/blast/tasks.rb +1 -1
- data/lib/sequenceserver/database.rb +5 -1
- data/lib/sequenceserver/job.rb +26 -10
- data/lib/sequenceserver/makeblastdb.rb +2 -1
- data/lib/sequenceserver/routes.rb +38 -13
- data/lib/sequenceserver/version.rb +1 -1
- data/lib/sequenceserver/zip_file_generator.rb +1 -1
- data/lib/sequenceserver.rb +1 -1
- data/public/404.html +8 -16
- data/public/css/app.css +794 -111
- data/public/css/app.min.css +1 -1
- data/public/css/sequenceserver.min.css +1 -8
- data/public/js/alignment_exporter.js +16 -28
- data/public/js/circos.js +103 -96
- data/public/{packages/circosJS@1.7.0.js → js/circosjs.js} +156 -778
- data/public/js/cloud_share_modal.js +95 -98
- data/public/js/collapse_preferences.js +13 -15
- data/public/js/databases.js +4 -3
- data/public/js/databases_tree.js +51 -30
- data/public/js/error_modal.js +35 -22
- data/public/js/exporter.js +2 -0
- data/public/js/form.js +55 -17
- data/public/js/grapher.js +94 -92
- data/public/js/hit.js +24 -22
- data/public/js/hits.js +283 -0
- data/public/js/hits_overview.js +8 -27
- data/public/js/hsp.js +140 -144
- data/public/js/jquery_world.js +25 -16
- data/public/js/kablammo.js +14 -10
- data/public/js/length_distribution.js +23 -37
- data/public/js/mailto.js +1 -3
- data/public/js/null_plugins/report_plugins.js +4 -5
- data/public/js/options.js +19 -25
- data/public/js/query.js +36 -35
- data/public/js/report/alignment_results.js +18 -0
- data/public/js/report/graphical_overview.js +38 -0
- data/public/js/report/report_header.js +28 -0
- data/public/js/report/run_summary.js +43 -0
- data/public/js/report.js +124 -348
- data/public/js/report_root.js +10 -8
- data/public/js/search.js +31 -11
- data/public/js/search_button.js +85 -78
- data/public/js/sequence.js +169 -180
- data/public/js/sequence_modal.js +58 -65
- data/public/js/share_url.js +5 -5
- data/public/js/sidebar.js +152 -89
- data/public/js/svgExporter.js +8 -3
- data/public/js/tests/alignment_exporter.spec.js +38 -0
- data/public/js/tests/cloud_share_modal.spec.js +75 -0
- data/public/js/tests/form.spec.js +1 -1
- data/public/js/tests/report.spec.js +37 -15
- data/public/js/tests/visualisation_helpers.spec.js +28 -0
- data/public/js/visualisation_helpers.js +24 -27
- data/public/packages/jquery-ui@1.13.3.js +19070 -0
- data/public/sequenceserver-report.min.js +3 -2481
- data/public/sequenceserver-report.min.js.LICENSE.txt +213 -0
- data/public/sequenceserver-report.min.js.map +1 -0
- data/public/sequenceserver-search.min.js +3 -2382
- data/public/sequenceserver-search.min.js.LICENSE.txt +262 -0
- data/public/sequenceserver-search.min.js.map +1 -0
- data/views/error.erb +1 -1
- data/views/layout.erb +122 -133
- data/views/report.erb +3 -2
- data/views/search.erb +10 -14
- metadata +21 -28
- data/public/config.js +0 -147
- data/public/css/fonts.css +0 -31
- data/public/css/grapher.css +0 -670
- data/public/css/sequenceserver.css +0 -527
- data/public/packages/jquery-ui@1.11.4.js +0 -16624
- data/public/vendor/github/mbostock/d3@3.5.6/d3.js +0 -9506
- data/public/vendor/github/mbostock/d3@3.5.6.js +0 -1
- data/views/search_layout.erb +0 -153
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import d3 from 'd3';
|
|
1
|
+
import * as d3 from 'd3';
|
|
2
2
|
import _ from 'underscore';
|
|
3
3
|
import Grapher from 'grapher';
|
|
4
4
|
import * as Helpers from './visualisation_helpers';
|
|
@@ -61,20 +61,19 @@ class Graph {
|
|
|
61
61
|
this.draw_rectangles();
|
|
62
62
|
this.draw_query_line();
|
|
63
63
|
this.draw_axes();
|
|
64
|
-
this.setupTooltip();
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
define_scale_and_bins() {
|
|
68
|
-
this._scale_x = d3.
|
|
67
|
+
this._scale_x = d3.scaleLinear()
|
|
69
68
|
.domain([
|
|
70
69
|
0,
|
|
71
70
|
(d3.max([this.query_length, d3.max(this._data)]) * 1.01)
|
|
72
71
|
]).nice()
|
|
73
72
|
.range([0, this._width]);
|
|
74
|
-
this._bins = d3.
|
|
75
|
-
.
|
|
76
|
-
.
|
|
77
|
-
this._scale_y = d3.
|
|
73
|
+
this._bins = d3.bin()
|
|
74
|
+
.domain(this._scale_x.domain())
|
|
75
|
+
.thresholds(this._scale_x.ticks(50))(this._data);
|
|
76
|
+
this._scale_y = d3.scaleLinear()
|
|
78
77
|
.domain([0, d3.max(this._bins, function(d) { return d.length; })])
|
|
79
78
|
.range([this._height, 0]).nice();
|
|
80
79
|
}
|
|
@@ -83,13 +82,6 @@ class Graph {
|
|
|
83
82
|
this._data = _.map(this.query.hits, _.iteratee('length'));
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
setupTooltip() {
|
|
87
|
-
this.svg_container.find('[data-toggle="tooltip"]').tooltip({
|
|
88
|
-
'placement': 'top', 'container': 'body', 'html': 'true',
|
|
89
|
-
'delay': 0, 'white-space': 'nowrap'
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
85
|
setupResponsiveness() {
|
|
94
86
|
var currentWidth = $(window).width();
|
|
95
87
|
console.log('cureent '+currentWidth);
|
|
@@ -104,20 +96,19 @@ class Graph {
|
|
|
104
96
|
}
|
|
105
97
|
|
|
106
98
|
tick_formatter(seq_type) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return
|
|
112
|
-
if (d === 0)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
} else {
|
|
117
|
-
return (format(prefix.scale(d)) + ' ' + prefix.symbol + suffixes[seq_type]);
|
|
118
|
-
}
|
|
99
|
+
const ticks = this._scale_x.ticks();
|
|
100
|
+
const prefix = d3.format('~s');
|
|
101
|
+
const suffixes = { amino_acid: 'aa', nucleic_acid: 'bp' };
|
|
102
|
+
|
|
103
|
+
return (d) => {
|
|
104
|
+
if (d === 0 || !ticks.includes(d)) return;
|
|
105
|
+
|
|
106
|
+
if (suffixes[seq_type] === 'aa') {
|
|
107
|
+
return `${d} ${suffixes[seq_type]}`;
|
|
119
108
|
} else {
|
|
120
|
-
|
|
109
|
+
const formatted = prefix(d);
|
|
110
|
+
|
|
111
|
+
return `${Helpers.formatNumberUnits(formatted)}${suffixes[seq_type]}`;
|
|
121
112
|
}
|
|
122
113
|
};
|
|
123
114
|
}
|
|
@@ -144,7 +135,7 @@ class Graph {
|
|
|
144
135
|
};
|
|
145
136
|
inner_data.push(item);
|
|
146
137
|
});
|
|
147
|
-
var item = {data: inner_data, x: bin.
|
|
138
|
+
var item = {data: inner_data, x: bin.x0, dx: bin.x1, length: bin.length};
|
|
148
139
|
data2.push(item);
|
|
149
140
|
});
|
|
150
141
|
this._update_data = data2;
|
|
@@ -166,13 +157,12 @@ class Graph {
|
|
|
166
157
|
.attr('xlink:href', function(i) { return i.url; })
|
|
167
158
|
.append('rect')
|
|
168
159
|
.attr('class','bar')
|
|
169
|
-
.attr('data-toggle','tooltip')
|
|
170
160
|
.attr('title', function(i) {
|
|
171
161
|
return i.id+' '+'<br>E value: '+Helpers.prettify_evalue(i.evalue)+'<br>Length: '+i.value;
|
|
172
162
|
})
|
|
173
163
|
.attr('x', 1)
|
|
174
164
|
.attr('y', function(i) { return (self._scale_y(i.y0)); })
|
|
175
|
-
.attr('width', self._scale_x(this._bins[1].
|
|
165
|
+
.attr('width', self._scale_x(this._bins[1].x0) - self._scale_x(this._bins[0].x0) - 1)
|
|
176
166
|
.attr('height', function (i) { return self._scale_y(i.y1) - self._scale_y(i.y0); })
|
|
177
167
|
.attr('fill', function(i) {
|
|
178
168
|
return i.color;
|
|
@@ -210,16 +200,12 @@ class Graph {
|
|
|
210
200
|
space = len;
|
|
211
201
|
}
|
|
212
202
|
var formatter = this.tick_formatter(this._seq_type.subject_seq_type);
|
|
213
|
-
var x_axis = d3.
|
|
214
|
-
.scale(this._scale_x)
|
|
215
|
-
.orient('bottom')
|
|
203
|
+
var x_axis = d3.axisTop(this._scale_x)
|
|
216
204
|
.ticks(50)
|
|
217
205
|
.tickFormat(formatter);
|
|
218
|
-
var y_axis = d3.
|
|
219
|
-
.scale(this._scale_y)
|
|
220
|
-
.orient('left')
|
|
206
|
+
var y_axis = d3.axisLeft(this._scale_y)
|
|
221
207
|
.tickValues(this._scale_y.ticks(space))
|
|
222
|
-
.
|
|
208
|
+
.tickSizeOuter(0)
|
|
223
209
|
.tickFormat(function (e) {
|
|
224
210
|
if (Math.floor(e) != e) {
|
|
225
211
|
return ;
|
data/public/js/mailto.js
CHANGED
|
@@ -5,9 +5,7 @@ export default function asMailtoHref(querydb, program, numQueries, url, isOpenAc
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
function formatDatabases(querydb) {
|
|
8
|
-
return querydb
|
|
9
|
-
.slice(0, 15)
|
|
10
|
-
.map(db => ' ' + db.title);
|
|
8
|
+
return querydb ? querydb.slice(0, 15).map(db => ' ' + db.title) : "";
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
function composeEmail(dbsArr, program, numQueries, url, isOpenAccess) {
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import Histogram from 'histogram';
|
|
2
|
+
import chroma from 'chroma-js';
|
|
2
3
|
|
|
3
4
|
class ReportPlugins {
|
|
4
5
|
constructor(parent) {
|
|
5
6
|
this.parent = parent;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
init() {
|
|
9
|
+
init(_callback) {
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
componentDidUpdate(_prevProps, _prevState) {
|
|
12
|
-
}
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
return
|
|
13
|
+
queryResult(_query) {
|
|
14
|
+
return null;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
generateStats() {
|
data/public/js/options.js
CHANGED
|
@@ -72,9 +72,10 @@ export class Options extends Component {
|
|
|
72
72
|
return (
|
|
73
73
|
<div id="options-presets" className="w-full">
|
|
74
74
|
{ Object.keys(this.props.predefinedOptions).length > 1 && <>
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
<div className="flex items-center border-b border-seqorange mb-2">
|
|
76
|
+
<h3 className="text-base md:text-lg font-medium pr-1">Settings</h3>
|
|
77
|
+
<p className="text-base text-gray-500">Choose a predefined setting or customize parameters.</p>
|
|
78
|
+
</div>
|
|
78
79
|
{this.presetListJSX()}
|
|
79
80
|
</>}
|
|
80
81
|
</div>
|
|
@@ -83,7 +84,7 @@ export class Options extends Component {
|
|
|
83
84
|
|
|
84
85
|
presetListJSX() {
|
|
85
86
|
return (
|
|
86
|
-
<ul className="text-
|
|
87
|
+
<ul className="md:text-lg my-1">
|
|
87
88
|
{
|
|
88
89
|
Object.entries(this.props.predefinedOptions).map(
|
|
89
90
|
([key, config], index) => {
|
|
@@ -91,7 +92,7 @@ export class Options extends Component {
|
|
|
91
92
|
let description = config.description || textValue;
|
|
92
93
|
|
|
93
94
|
return (
|
|
94
|
-
<label key={index} className={`block w-full px-2 py-1 hover:bg-gray-200 cursor-pointer`}>
|
|
95
|
+
<label key={index} className={`block w-full px-2 py-1 text-seqblue hover:bg-gray-200 hover:text-seqorange cursor-pointer`}>
|
|
95
96
|
<input
|
|
96
97
|
type="radio"
|
|
97
98
|
name="predefinedOption"
|
|
@@ -110,39 +111,29 @@ export class Options extends Component {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
advancedParamsJSX() {
|
|
113
|
-
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
let classNames = 'flex-grow block px-4 py-1 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 text-base';
|
|
114
|
+
let classNames = 'flex-grow block px-4 py-1 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 text-base font-mono';
|
|
118
115
|
|
|
119
116
|
if (this.state.textValue) {
|
|
120
117
|
classNames += ' bg-yellow-100';
|
|
121
118
|
}
|
|
122
119
|
|
|
123
120
|
return(
|
|
124
|
-
|
|
121
|
+
<div className={this.state.paramsMode !== 'advanced' ? 'w-full hidden' : 'w-full'}>
|
|
125
122
|
<div className="flex items-end">
|
|
126
|
-
<label className="flex items-center" htmlFor="advanced">
|
|
127
|
-
|
|
123
|
+
<label className="flex items-center text-base md:text-lg" htmlFor="advanced">
|
|
124
|
+
Parameters:
|
|
128
125
|
</label>
|
|
129
126
|
|
|
130
127
|
{this.props.blastMethod &&
|
|
131
128
|
<button
|
|
132
|
-
className="text-seqblue ml-2"
|
|
129
|
+
className="text-seqblue text-base md:text-lg ml-2"
|
|
133
130
|
type="button"
|
|
134
131
|
onClick={this.showAdvancedOptionsHelp}
|
|
135
132
|
data-toggle="modal" data-target="#help">
|
|
136
|
-
See
|
|
133
|
+
See options
|
|
137
134
|
<i className="fa fa-question-circle ml-1 w-3 h-4 fill-current"></i>
|
|
138
135
|
</button>
|
|
139
136
|
}
|
|
140
|
-
|
|
141
|
-
{!this.props.blastMethod &&
|
|
142
|
-
<span className="text-gray-600 ml-2 text-sm hidden sm:block">
|
|
143
|
-
Select databases and fill in the query to see options.
|
|
144
|
-
</span>
|
|
145
|
-
}
|
|
146
137
|
</div>
|
|
147
138
|
|
|
148
139
|
<div className='flex-grow flex w-full'>
|
|
@@ -155,8 +146,8 @@ export class Options extends Component {
|
|
|
155
146
|
title="View, and enter advanced parameters."
|
|
156
147
|
/>
|
|
157
148
|
</div>
|
|
158
|
-
<div className="
|
|
159
|
-
Options as they would appear in a command
|
|
149
|
+
<div className="mt-1 text-gray-700">
|
|
150
|
+
Options as they would appear in a command-line.
|
|
160
151
|
</div>
|
|
161
152
|
</div>
|
|
162
153
|
)
|
|
@@ -165,15 +156,18 @@ export class Options extends Component {
|
|
|
165
156
|
showAdvancedOptionsHelp(e) {
|
|
166
157
|
const ids = ['blastn', 'tblastn', 'blastp', 'blastx', 'tblastx'];
|
|
167
158
|
const method = this.props.blastMethod.toLowerCase();
|
|
159
|
+
const modal = document.querySelector("dialog.advanced-modal");
|
|
160
|
+
|
|
168
161
|
// hide options for other algorithms and only show for selected algorithm
|
|
169
162
|
for (const id of ids) {
|
|
170
163
|
if (id === method) {
|
|
171
|
-
document.getElementById(id).classList.remove('hidden')
|
|
164
|
+
document.getElementById(id).classList.remove('hidden');
|
|
172
165
|
} else {
|
|
173
166
|
document.getElementById(id).classList.add('hidden');
|
|
174
167
|
}
|
|
175
168
|
}
|
|
176
|
-
|
|
169
|
+
|
|
170
|
+
modal.showModal();
|
|
177
171
|
}
|
|
178
172
|
|
|
179
173
|
render() {
|
data/public/js/query.js
CHANGED
|
@@ -6,6 +6,7 @@ import LengthDistribution from './length_distribution'; // length distribution o
|
|
|
6
6
|
import Utils from './utils';
|
|
7
7
|
import { fastqToFasta } from './fastq_to_fasta';
|
|
8
8
|
import CollapsePreferences from './collapse_preferences';
|
|
9
|
+
import './jquery_world';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Query component displays query defline, graphical overview, length
|
|
@@ -44,21 +45,22 @@ export class ReportQuery extends Component {
|
|
|
44
45
|
return this.props.query.hits.length;
|
|
45
46
|
}
|
|
46
47
|
headerJSX() {
|
|
47
|
-
var meta = `
|
|
48
|
+
var meta = `Length: ${this.queryLength().toLocaleString()}`;
|
|
49
|
+
|
|
48
50
|
if (this.props.showQueryCrumbs) {
|
|
49
|
-
meta = `query ${this.props.query.number}
|
|
51
|
+
meta = `query ${this.props.query.number}. ${meta}`;
|
|
50
52
|
}
|
|
51
|
-
return <div className="section-header">
|
|
52
|
-
<h3>
|
|
53
|
-
<strong>Query
|
|
54
|
-
{this.props.query.title}
|
|
53
|
+
return <div className="section-header border-b border-seqorange justify-between w-full flex flex-col sm:flex-row gap-4">
|
|
54
|
+
<h3 className="text-base cursor-pointer flex flex-col sm:flex-row items-start">
|
|
55
|
+
<strong>Query=<span className="ml-1">{this.props.query.id}</span></strong>
|
|
56
|
+
<span className="ml-1">{this.props.query.title}</span>
|
|
55
57
|
</h3>
|
|
56
|
-
<span className="label
|
|
58
|
+
<span className="label first-letter:capitalize text-sm text-right font-normal text-inherit pt-0 px-0">{meta}</span>
|
|
57
59
|
</div>;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
hitsListJSX() {
|
|
61
|
-
return <div className="
|
|
63
|
+
return <div className="pt-0 px-0 pb-px">
|
|
62
64
|
<HitsOverview key={'GO_' + this.props.query.number} query={this.props.query} program={this.props.program} collapsed={this.props.veryBig} />
|
|
63
65
|
<LengthDistribution key={'LD_' + this.props.query.id} query={this.props.query} algorithm={this.props.program} />
|
|
64
66
|
<HitsTable key={'HT_' + this.props.query.number} query={this.props.query} imported_xml={this.props.imported_xml} />
|
|
@@ -66,14 +68,14 @@ export class ReportQuery extends Component {
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
noHitsJSX() {
|
|
69
|
-
return <div className="
|
|
71
|
+
return <div className="pt-0 px-0 pb-px">
|
|
70
72
|
<strong> ****** No BLAST hits found ****** </strong>
|
|
71
73
|
</div>;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
render() {
|
|
75
77
|
return (
|
|
76
|
-
<div className="resultn" id={this.domID()}
|
|
78
|
+
<div className="resultn mt-1.5" id={this.domID()}
|
|
77
79
|
data-query-len={this.props.query.length}
|
|
78
80
|
data-algorithm={this.props.program}>
|
|
79
81
|
{this.headerJSX()}
|
|
@@ -348,7 +350,7 @@ export class SearchQueryWidget extends Component {
|
|
|
348
350
|
className="sequence">
|
|
349
351
|
<textarea
|
|
350
352
|
id="sequence" ref={this.textareaRef}
|
|
351
|
-
className="block w-full p-4 text-gray-900 border border-gray-300 rounded-l-lg rounded-tr-lg bg-gray-50 text-
|
|
353
|
+
className="block w-full p-4 text-gray-900 border border-gray-300 rounded-l-lg rounded-tr-lg bg-gray-50 text-sm font-mono min-h-52 resize-y"
|
|
352
354
|
name="sequence" value={this.state.value}
|
|
353
355
|
rows="6"
|
|
354
356
|
required="required"
|
|
@@ -408,16 +410,16 @@ class HitsTable extends Component {
|
|
|
408
410
|
if (this.props.imported_xml) seqwidth += 15;
|
|
409
411
|
|
|
410
412
|
return <table
|
|
411
|
-
className="table table-hover table-condensed tabular-view ">
|
|
413
|
+
className="table table-hover table-condensed tabular-view text-sm min-w-full mb-0">
|
|
412
414
|
<thead>
|
|
413
|
-
<tr>
|
|
414
|
-
<th className="text-left">#</th>
|
|
415
|
-
<th
|
|
416
|
-
{hasName && <th
|
|
417
|
-
{!this.props.imported_xml && <th
|
|
418
|
-
<th
|
|
419
|
-
<th
|
|
420
|
-
<th
|
|
415
|
+
<tr className="text-neutral-500">
|
|
416
|
+
<th className="text-left font-normal">#</th>
|
|
417
|
+
<th style={{ width: `${seqwidth}%` }} className="text-left font-normal">Similar sequences</th>
|
|
418
|
+
{hasName && <th className="text-left font-normal w-2/12">Species</th>}
|
|
419
|
+
{!this.props.imported_xml && <th className="text-right font-normal w-2/12">Query coverage (%)</th>}
|
|
420
|
+
<th className="text-right font-normal w-1/12">Total score</th>
|
|
421
|
+
<th className="text-right font-normal w-1/12">E value</th>
|
|
422
|
+
<th className="text-right font-normal w-1/12">Identity (%)</th>
|
|
421
423
|
</tr>
|
|
422
424
|
</thead>
|
|
423
425
|
<tbody>
|
|
@@ -426,22 +428,19 @@ class HitsTable extends Component {
|
|
|
426
428
|
return (
|
|
427
429
|
<tr key={hit.number}>
|
|
428
430
|
<td className="text-left">{hit.number + '.'}</td>
|
|
429
|
-
<td
|
|
430
|
-
title={`${hit.id} ${hit.title}`}
|
|
431
|
-
data-toggle="tooltip" data-placement="left">
|
|
431
|
+
<td>
|
|
432
432
|
<a href={'#Query_' + this.props.query.number + '_hit_' + hit.number}
|
|
433
|
-
className="
|
|
433
|
+
className="text-sm text-seqblue hover:text-seqorange cursor-pointer pe-1 line-clamp-1 tooltip-item" title={`${hit.id} ${hit.title}`}>{hit.id} {hit.title}</a>
|
|
434
434
|
</td>
|
|
435
435
|
{hasName &&
|
|
436
|
-
<td className="
|
|
437
|
-
data-toggle="tooltip" data-placement="top">
|
|
436
|
+
<td className="pe-1 line-clamp-1 tooltip-item" title={hit.sciname}>
|
|
438
437
|
{hit.sciname}
|
|
439
438
|
</td>
|
|
440
439
|
}
|
|
441
440
|
{!this.props.imported_xml && <td className="text-right">{hit.qcovs}</td>}
|
|
442
|
-
<td className="text-right">{hit.total_score}</td>
|
|
443
|
-
<td className="text-right">{Utils.inExponential(hit.hsps[0].evalue)}</td>
|
|
444
|
-
<td className="text-right">{Utils.inPercentage(hit.hsps[0].identity, hit.hsps[0].length)}</td>
|
|
441
|
+
<td className="pe-1 text-right">{hit.total_score}</td>
|
|
442
|
+
<td className="pe-1 text-right">{Utils.inExponential(hit.hsps[0].evalue)}</td>
|
|
443
|
+
<td className="pe-1 text-right">{Utils.inPercentage(hit.hsps[0].identity, hit.hsps[0].length)}</td>
|
|
445
444
|
</tr>
|
|
446
445
|
);
|
|
447
446
|
}, this))
|
|
@@ -452,12 +451,14 @@ class HitsTable extends Component {
|
|
|
452
451
|
|
|
453
452
|
render() {
|
|
454
453
|
return (
|
|
455
|
-
<div className=
|
|
456
|
-
<
|
|
457
|
-
{this.collapsePreferences.
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
454
|
+
<div className={`table-hit-overview ${this.state.collapsed ? 'print:hidden' : ''}`}>
|
|
455
|
+
<div className="grapher-header pr-px">
|
|
456
|
+
<h4 className="inline-block pl-px m-0 caption cursor-pointer text-sm caption" onClick={() => this.collapsePreferences.toggleCollapse()}>
|
|
457
|
+
{this.collapsePreferences.renderCollapseIcon()}
|
|
458
|
+
<span> {this.name}</span>
|
|
459
|
+
</h4>
|
|
460
|
+
</div>
|
|
461
|
+
<div id={'Query_' + this.props.query.number + 'HT_' + this.props.query.number} className="overflow-auto md:overflow-hidden">
|
|
461
462
|
{!this.state.collapsed && this.tableJSX()}
|
|
462
463
|
</div>
|
|
463
464
|
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import ReportHeader from './report_header';
|
|
2
|
+
import Hits from '../hits';
|
|
3
|
+
|
|
4
|
+
const AlignmentResults = (props) => {
|
|
5
|
+
const renderContent = () => (
|
|
6
|
+
<div>
|
|
7
|
+
{props.state.results}
|
|
8
|
+
<Hits
|
|
9
|
+
{...props}
|
|
10
|
+
componentFinishedUpdating={(_) => props.componentFinishedUpdating(_)}
|
|
11
|
+
/>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return <ReportHeader name="Alignment Results" renderContent={renderContent} />;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default AlignmentResults;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Circos from '../circos';
|
|
2
|
+
import ReportHeader from './report_header';
|
|
3
|
+
|
|
4
|
+
const GraphicalOverview = ({queries, program, plugins}) => {
|
|
5
|
+
/**
|
|
6
|
+
* Does the report have at least two hits? This is used to determine
|
|
7
|
+
* whether Circos should be enabled or not.
|
|
8
|
+
*/
|
|
9
|
+
const atLeastTwoHits = () => {
|
|
10
|
+
let hitNum = 0;
|
|
11
|
+
return queries.some((query) => {
|
|
12
|
+
hitNum += query.hits.length;
|
|
13
|
+
return hitNum > 1;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const renderContent = () => {
|
|
18
|
+
if(!atLeastTwoHits()) return null;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<Circos queries={queries} program={program} />
|
|
23
|
+
{plugins.generateStats(queries)}
|
|
24
|
+
</>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<ReportHeader
|
|
30
|
+
name="Graphical Overview"
|
|
31
|
+
renderContent={renderContent}
|
|
32
|
+
renderable={atLeastTwoHits()}
|
|
33
|
+
defaultCollapsed={true}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default GraphicalOverview;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import CollapsePreferences from '../collapse_preferences';
|
|
3
|
+
|
|
4
|
+
const ReportHeader = (props) => {
|
|
5
|
+
const [state, setState] = useState({ collapsed: null });
|
|
6
|
+
const [renderable, _setRenderable] = useState(props.renderable === undefined ? true : props.renderable);
|
|
7
|
+
const collapsePreferences = new CollapsePreferences(
|
|
8
|
+
{ name: props.name, state: { ...state }, setState: setState },
|
|
9
|
+
props.defaultCollapsed
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
if (state.collapsed === null) setState({ collapsed: collapsePreferences.preferenceStoredAsCollapsed() });
|
|
13
|
+
if (!renderable) return null;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className={`${state.collapsed ? 'print:!hidden' : ''}`}>
|
|
17
|
+
<h3 className="caption font-bold border-b-2 border-seqorange" onClick={() => collapsePreferences.toggleCollapse()}>
|
|
18
|
+
{collapsePreferences.renderCollapseIcon()}
|
|
19
|
+
<span> {props.name}</span>
|
|
20
|
+
</h3>
|
|
21
|
+
<div className='mx-1 print:mx-0'>
|
|
22
|
+
{!state.collapsed && props.renderContent()}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default ReportHeader;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import ReportHeader from './report_header';
|
|
2
|
+
import _ from 'underscore';
|
|
3
|
+
|
|
4
|
+
const RunSummary = (props) => {
|
|
5
|
+
const renderContent = () => {
|
|
6
|
+
return (
|
|
7
|
+
<div className="overview mr-0 mb-0">
|
|
8
|
+
<p className="m-0 text-sm">
|
|
9
|
+
<strong>SequenceServer {props.seqserv_version}</strong> using{' '}
|
|
10
|
+
<strong>{props.program_version}</strong>
|
|
11
|
+
{props.submitted_at &&
|
|
12
|
+
`, query submitted on ${props.submitted_at}`}
|
|
13
|
+
</p>
|
|
14
|
+
<p className="m-0 text-sm">
|
|
15
|
+
<strong> Databases: </strong>
|
|
16
|
+
{props.querydb
|
|
17
|
+
.map((db) => {
|
|
18
|
+
return db.title;
|
|
19
|
+
})
|
|
20
|
+
.join(', ')}{' '}
|
|
21
|
+
({props.stats.nsequences} sequences,
|
|
22
|
+
{props.stats.ncharacters} characters)
|
|
23
|
+
</p>
|
|
24
|
+
<p className="m-0 text-sm">
|
|
25
|
+
<strong>Parameters: </strong>{' '}
|
|
26
|
+
{_.map(props.params, function (val, key) {
|
|
27
|
+
return key + ' ' + val;
|
|
28
|
+
}).join(', ')}
|
|
29
|
+
</p>
|
|
30
|
+
<p className="m-0 text-sm">
|
|
31
|
+
Please cite:{' '}
|
|
32
|
+
<a href="https://doi.org/10.1093/molbev/msz185" className="text-seqblue hover:text-seqorange">
|
|
33
|
+
https://doi.org/10.1093/molbev/msz185
|
|
34
|
+
</a>
|
|
35
|
+
</p>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return <ReportHeader name="Run Summary" renderContent={renderContent} />;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default RunSummary;
|