sequenceserver 1.1.0.beta2 → 1.1.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +16 -5
- data/README.md +3 -0
- data/lib/sequenceserver/api_errors.rb +67 -0
- data/lib/sequenceserver/blast/constants.rb +1 -1
- data/lib/sequenceserver/blast/formatter.rb +4 -2
- data/lib/sequenceserver/blast/job.rb +17 -62
- data/lib/sequenceserver/blast/report.rb +15 -2
- data/lib/sequenceserver/blast.rb +1 -0
- data/lib/sequenceserver/exceptions.rb +2 -3
- data/lib/sequenceserver/job.rb +72 -44
- data/lib/sequenceserver/routes.rb +29 -25
- data/lib/sequenceserver/version.rb +1 -1
- data/lib/sequenceserver.rb +32 -20
- data/public/js/errormodal.js +55 -0
- data/public/js/report.js +6 -2
- data/public/js/sequenceserver.js +0 -12
- data/public/sequenceserver-report.min.js +15 -15
- data/public/sequenceserver-search.min.js +3 -3
- data/sequenceserver.gemspec +2 -1
- data/spec/capybara_spec.rb +120 -21
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhd +8 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nhi +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.nog +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsd +16 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsi +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.fasta.nsq +0 -0
- data/spec/database/sample/genome/Solenopsis_invicta/Solenopsis_invicta_gnG_subset.txt +8 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phd +9140 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.phi +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.pog +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psd +18280 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psi +0 -0
- data/spec/database/sample/proteins/uniprot/2018-04-Swiss-Prot_insecta.fasta.psq +0 -0
- data/spec/database/sample/proteins/uniprot/URL +1 -0
- data/spec/nucleotide_query.fa +21 -0
- data/spec/protein_query.fa +21 -0
- data/spec/routes_spec.rb +2 -0
- data/spec/sample_reports/blastn_sample/job.yaml +1 -0
- data/spec/sample_reports/blastn_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/blastp_sample/job.yaml +1 -0
- data/spec/sample_reports/blastp_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/blastx_sample/job.yaml +1 -0
- data/spec/sample_reports/blastx_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/no_hits_sample/job.yaml +1 -0
- data/spec/sample_reports/no_hits_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/tblastn_sample/job.yaml +1 -0
- data/spec/sample_reports/tblastn_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/tblastx_sample/job.yaml +1 -0
- data/spec/sample_reports/tblastx_sample/{rfile → stdout} +0 -0
- data/spec/sample_reports/with_hits_sample/job.yaml +1 -0
- data/spec/sample_reports/with_hits_sample/{rfile → stdout} +0 -0
- data/spec/sequenceserver_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -16
- data/views/layout.erb +0 -45
- metadata +55 -16
- data/lib/sequenceserver/blast/exceptions.rb +0 -27
- data/views/400.erb +0 -29
- data/views/500.erb +0 -41
data/lib/sequenceserver.rb
CHANGED
@@ -90,11 +90,15 @@ module SequenceServer
|
|
90
90
|
# sys(command, :dir => '/path/to/directory',
|
91
91
|
# :path => '/path/to/directory', :stdout => '/path/to/stdout_file',
|
92
92
|
# :stderr => '/path/to/stderr_file')
|
93
|
-
|
94
93
|
def sys(command, options = {})
|
94
|
+
# Available output channels
|
95
|
+
channels = [:stdout, :stderr]
|
96
|
+
|
95
97
|
# Make temporary files to store output from stdout and stderr.
|
96
|
-
|
97
|
-
|
98
|
+
temp_files = {
|
99
|
+
stdout: Tempfile.new('sequenceserver-sys'),
|
100
|
+
stderr: Tempfile.new('sequenceserver-sys')
|
101
|
+
}
|
98
102
|
|
99
103
|
# Log the command we are going to run - use -D option to view.
|
100
104
|
logger.debug("Executing: #{command}")
|
@@ -111,32 +115,40 @@ module SequenceServer
|
|
111
115
|
|
112
116
|
# Execute the shell command, redirect stdout and stderr to the
|
113
117
|
# temporary files.
|
114
|
-
exec("#{command} 1>#{
|
118
|
+
exec("#{command} 1>#{temp_files[:stdout].path}" \
|
119
|
+
" 2>#{temp_files[:stderr].path}")
|
115
120
|
end
|
116
121
|
|
117
122
|
# Wait for the termination of the child process.
|
118
123
|
_, status = Process.wait2(child_pid)
|
119
124
|
|
120
|
-
|
121
|
-
|
125
|
+
# If a full path was given for stdout and stderr files, move the
|
126
|
+
# temporary files to this path. If the path given does not exist,
|
127
|
+
# create it.
|
128
|
+
channels.each do |channel|
|
129
|
+
filename = options[channel]
|
130
|
+
break unless filename
|
131
|
+
|
132
|
+
# If the given path has a directory component, ensure it exists.
|
133
|
+
file_dir = File.dirname(filename)
|
134
|
+
FileUtils.mkdir_p(file_dir) unless File.directory?(file_dir)
|
135
|
+
|
136
|
+
# Now move the temporary file to the given path.
|
137
|
+
# TODO: don't we need to explicitly close the temp file here?
|
138
|
+
FileUtils.mv(temp_files.delete(channel), filename)
|
122
139
|
end
|
123
140
|
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
file_dir = File.dirname(filename)
|
130
|
-
unless File.directory?(file_dir)
|
131
|
-
FileUtils.mkdir_p(file_dir)
|
132
|
-
end
|
133
|
-
FileUtils.mv([temp_stdout_file, temp_stderr_file][index], filename)
|
134
|
-
end
|
141
|
+
# Read the remaining temp files into memory. For large outputs,
|
142
|
+
# the caller should supply a file path to prevent loading the
|
143
|
+
# output in memory.
|
144
|
+
temp_files.each do |channel, tempfile|
|
145
|
+
temp_files[channel] = tempfile.read
|
135
146
|
end
|
136
147
|
|
137
|
-
#
|
138
|
-
#
|
139
|
-
return
|
148
|
+
# Finally, return contents of the remaining temp files if the
|
149
|
+
# command completed successfully or raise CommandFailed error.
|
150
|
+
return temp_files.values if status.success?
|
151
|
+
raise CommandFailed.new(status.exitstatus, **temp_files)
|
140
152
|
end
|
141
153
|
|
142
154
|
# Run SequenceServer as a self-hosted server using Thin webserver.
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
class ErrorModal extends React.Component {
|
4
|
+
|
5
|
+
constructor(props) {
|
6
|
+
super(props);
|
7
|
+
}
|
8
|
+
|
9
|
+
render() {
|
10
|
+
return (
|
11
|
+
<div
|
12
|
+
id="error" ref="errorModal" className="modal fade"
|
13
|
+
data-keyboard="false" data-backdrop="static">
|
14
|
+
<div
|
15
|
+
className="modal-dialog modal-lg">
|
16
|
+
<div
|
17
|
+
className="modal-content">
|
18
|
+
<div
|
19
|
+
className="modal-header">
|
20
|
+
<h3>{this.props.errorData.title}</h3>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div
|
24
|
+
className="modal-body">
|
25
|
+
<p dangerouslySetInnerHTML={{ __html: this.props.errorData.message}}></p>
|
26
|
+
|
27
|
+
{
|
28
|
+
this.props.errorData.more_info &&
|
29
|
+
<pre className="pre-scrollable">
|
30
|
+
{this.props.errorData.more_info}
|
31
|
+
</pre>
|
32
|
+
}
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
);
|
38
|
+
}
|
39
|
+
|
40
|
+
componentDidMount() {
|
41
|
+
$(React.findDOMNode(this.refs.errorModal)).modal('show');
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
export default function showErrorModal (errorData, beforeShow) {
|
46
|
+
if (!beforeShow) {
|
47
|
+
beforeShow = function () {};
|
48
|
+
}
|
49
|
+
|
50
|
+
setTimeout(function () {
|
51
|
+
beforeShow();
|
52
|
+
React.render(<ErrorModal errorData={errorData}/>,
|
53
|
+
document.getElementById('view'));
|
54
|
+
}, 500);
|
55
|
+
}
|
data/public/js/report.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
import SequenceServer from './sequenceserver';
|
2
|
+
import showErrorModal from './errormodal';
|
3
|
+
|
2
4
|
import _ from 'underscore';
|
3
5
|
import React from 'react';
|
4
6
|
import d3 from 'd3';
|
@@ -272,7 +274,7 @@ var SequenceViewer = (function () {
|
|
272
274
|
})
|
273
275
|
}, this))
|
274
276
|
.fail(function (jqXHR, status, error) {
|
275
|
-
|
277
|
+
showErrorModal(jqXHR, function () {
|
276
278
|
this.hide();
|
277
279
|
});
|
278
280
|
});
|
@@ -989,8 +991,10 @@ var Report = React.createClass({
|
|
989
991
|
case 200:
|
990
992
|
this.setState(jqXHR.responseJSON);
|
991
993
|
break;
|
994
|
+
case 404:
|
995
|
+
case 400:
|
992
996
|
case 500:
|
993
|
-
|
997
|
+
showErrorModal(jqXHR.responseJSON);
|
994
998
|
break;
|
995
999
|
}
|
996
1000
|
}, this));
|
data/public/js/sequenceserver.js
CHANGED
@@ -107,16 +107,4 @@ export default {
|
|
107
107
|
$(this).tooltip();
|
108
108
|
});
|
109
109
|
},
|
110
|
-
|
111
|
-
showErrorModal: function (jqXHR, beforeShow) {
|
112
|
-
setTimeout(function () {
|
113
|
-
beforeShow();
|
114
|
-
if (jqXHR.responseText) {
|
115
|
-
$("#error").html(jqXHR.responseText).modal();
|
116
|
-
}
|
117
|
-
else {
|
118
|
-
$("#error-no-response").modal();
|
119
|
-
}
|
120
|
-
}, 500);
|
121
|
-
}
|
122
110
|
};
|