sequenceserver 0.6.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE.txt +64 -0
- data/README.txt +5 -0
- data/bin/database_formatter +195 -0
- data/bin/sequenceserver +12 -0
- data/config.ru +5 -0
- data/example.config.yml +39 -0
- data/lib/sequenceserver/blast.rb +211 -0
- data/lib/sequenceserver/customisation.rb +60 -0
- data/lib/sequenceserver/database.rb +23 -0
- data/lib/sequenceserver/helpers.rb +127 -0
- data/lib/sequenceserver/sequencehelpers.rb +119 -0
- data/lib/sequenceserver/sinatralikeloggerformatter.rb +12 -0
- data/lib/sequenceserver.rb +525 -0
- data/public/blastResult.js +99 -0
- data/public/css/bootstrap.min.css +330 -0
- data/public/css/custom.css +92 -0
- data/public/js/jquery.enablePlaceholder.min.js +11 -0
- data/public/js/jquery.js +18 -0
- data/public/js/search.js +148 -0
- data/sequenceserver.gemspec +42 -0
- data/tests/database/nucleotide/Sinvicta2-2-3.cdna.subset.fasta +5486 -0
- data/tests/database/nucleotide/Sinvicta2-2-3.cdna.subset.fasta.nhr +0 -0
- data/tests/database/nucleotide/Sinvicta2-2-3.cdna.subset.fasta.nin +0 -0
- data/tests/database/nucleotide/Sinvicta2-2-3.cdna.subset.fasta.nsq +0 -0
- data/tests/database/protein/Sinvicta2-2-3.prot.subset.fasta +6449 -0
- data/tests/database/protein/Sinvicta2-2-3.prot.subset.fasta.phr +0 -0
- data/tests/database/protein/Sinvicta2-2-3.prot.subset.fasta.pin +0 -0
- data/tests/database/protein/Sinvicta2-2-3.prot.subset.fasta.psq +0 -0
- data/tests/test_sequencehelpers.rb +85 -0
- data/views/500.erb +22 -0
- data/views/search.erb +221 -0
- metadata +141 -0
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
SequenceServer (http://sequenceserver.com)
|
2
|
+
Copyright (c) 2010-2011 Yannick Wurm, Benjamin J. Woodcroft, Anurag Priyam.
|
3
|
+
|
4
|
+
|
5
|
+
1. Definitions
|
6
|
+
|
7
|
+
The software: the SequenceServer software and associated documentation.
|
8
|
+
The authors: Yannick Wurm, Anurag Priyam, Benjamin J. Woodcroft.
|
9
|
+
|
10
|
+
|
11
|
+
2. Fair usage
|
12
|
+
|
13
|
+
Within not-for-profit and educational organizations the software can
|
14
|
+
be freely used by individuals and on internal and public websites.
|
15
|
+
|
16
|
+
Installation of the software or use of the software by for-profit
|
17
|
+
organizations (including but not limited to companies, service providers
|
18
|
+
and consultancies) requires purchase of a usage license or other specific
|
19
|
+
arrangements with the authors.
|
20
|
+
|
21
|
+
|
22
|
+
3. Modifications
|
23
|
+
|
24
|
+
Modifications can be made by not-for-profit and educational organizations.
|
25
|
+
However, citation requests and links to sequenceserver.com must remain
|
26
|
+
visible and unaltered.
|
27
|
+
|
28
|
+
|
29
|
+
4. Redistribution of the software
|
30
|
+
|
31
|
+
Redistribution without modification is permitted unless associated to
|
32
|
+
a financial transaction. In particular, the software may not be
|
33
|
+
distributed with nor installed via a commercial software package, nor
|
34
|
+
be made available by commercial service providers.
|
35
|
+
|
36
|
+
Redistribution with modification is permitted only if ALL of the
|
37
|
+
following conditions are respected:
|
38
|
+
|
39
|
+
a. no financial transaction is associated (see above).
|
40
|
+
b. This license and copyright notices are included and remain
|
41
|
+
unchanged; citation requests and links to sequenceserver.com
|
42
|
+
remain visible and unaltered.
|
43
|
+
c. Modifications are made freely available on github.com (or an
|
44
|
+
equivalent medium) and the authors are allowed to freely
|
45
|
+
incorporate modifications into the software.
|
46
|
+
|
47
|
+
|
48
|
+
5. Specific needs
|
49
|
+
|
50
|
+
The authors reserve the right to make specific licensing, modification
|
51
|
+
and distribution arrangements with interested parties.
|
52
|
+
|
53
|
+
|
54
|
+
6. Disclaimer
|
55
|
+
|
56
|
+
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
57
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
58
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
59
|
+
PURPOSE. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
60
|
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
61
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
62
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
63
|
+
SOFTWARE.
|
64
|
+
|
data/README.txt
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# copyright yannick . wurm at unil . ch
|
3
|
+
# Finds files, reads first char. if its '>', read 500 lines. Guess sequence type, ask user for title to format as blast database.
|
4
|
+
|
5
|
+
# ensure 'lib/' is in the load path
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'ptools' # for File.binary?(file)
|
10
|
+
require 'find'
|
11
|
+
require 'logger'
|
12
|
+
require 'optparse'
|
13
|
+
require 'sequenceserver'
|
14
|
+
require 'sequenceserver/helpers.rb'
|
15
|
+
require 'sequenceserver/sequencehelpers.rb'
|
16
|
+
|
17
|
+
LOG = Logger.new(STDOUT)
|
18
|
+
LOG.level = Logger::INFO
|
19
|
+
|
20
|
+
class DatabaseFormatter
|
21
|
+
include SequenceServer
|
22
|
+
include Helpers
|
23
|
+
include SystemHelpers
|
24
|
+
include SequenceHelpers
|
25
|
+
|
26
|
+
attr_accessor :db_path
|
27
|
+
|
28
|
+
def initialize(db_path = nil)
|
29
|
+
@app = SequenceServer::App
|
30
|
+
@app.config = @app.parse_config
|
31
|
+
@app.binaries = @app.scan_blast_executables(@app.bin).freeze
|
32
|
+
|
33
|
+
@db_path = (db_path or @app.database)
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_databases
|
37
|
+
unless File.directory?(db_path)
|
38
|
+
LOG.fatal("Database directory #{db_path} not found. See './database_formatter --help' for instructions.")
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
formatted_dbs = %x|#{@app.binaries['blastdbcmd']} -recursive -list #{db_path} -list_outfmt "%f" 2>&1|.split("\n")
|
43
|
+
commands = []
|
44
|
+
Find.find(db_path) do |file|
|
45
|
+
LOG.debug("Assessing file #{file}..")
|
46
|
+
if File.directory?(file)
|
47
|
+
LOG.debug("Ignoring file #{file} since it is a directory")
|
48
|
+
next
|
49
|
+
end
|
50
|
+
if formatted_dbs.include?(file)
|
51
|
+
LOG.debug("Ignoring file #{file} since it is already a blast database")
|
52
|
+
next
|
53
|
+
end
|
54
|
+
if File.binary?(file)
|
55
|
+
LOG.debug("Ignoring file #{file} since it is a binary file, not plaintext as FASTA files are")
|
56
|
+
next
|
57
|
+
end
|
58
|
+
|
59
|
+
if probably_fasta?(file)
|
60
|
+
LOG.info("Found #{file}")
|
61
|
+
## guess whether protein or nucleotide based on first 500 lines
|
62
|
+
first_lines = ''
|
63
|
+
File.open(file, 'r') do |file_stream|
|
64
|
+
file_stream.each do |line|
|
65
|
+
first_lines += line
|
66
|
+
break if file_stream.lineno == 500
|
67
|
+
end
|
68
|
+
end
|
69
|
+
begin
|
70
|
+
sequence_type = type_of_sequences(first_lines) # returns :protein or :nucleotide
|
71
|
+
rescue
|
72
|
+
LOG.warn("Unable to guess sequence type for #{file}. Skipping")
|
73
|
+
end
|
74
|
+
if [ :protein, :nucleotide ].include?(sequence_type)
|
75
|
+
command = ask_make_db_command(file, sequence_type)
|
76
|
+
unless command.nil?
|
77
|
+
commands.push(command)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
LOG.warn("Unable to guess sequence type for #{file}. Skipping")
|
81
|
+
end
|
82
|
+
else
|
83
|
+
LOG.debug("Ignoring file #{file} since it was not judged to be a FASTA file.")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
LOG.info("Will now create DBs")
|
87
|
+
if commands.empty?
|
88
|
+
puts "", "#{db_path} does not contain any unformatted database."
|
89
|
+
exit
|
90
|
+
end
|
91
|
+
commands.each do |command|
|
92
|
+
LOG.info("Will run: " + command.to_s)
|
93
|
+
system(command)
|
94
|
+
end
|
95
|
+
LOG.info("Done formatting databases. ")
|
96
|
+
db_table(db_path)
|
97
|
+
end
|
98
|
+
|
99
|
+
def db_table(db_path)
|
100
|
+
LOG.info("Summary of formatted blast databases:\n")
|
101
|
+
output = %x|#{@app.binaries['blastdbcmd']} -recursive -list #{db_path} -list_outfmt "%p %f %t" &2>1 |
|
102
|
+
LOG.info(output)
|
103
|
+
end
|
104
|
+
|
105
|
+
def probably_fasta?(file)
|
106
|
+
return FALSE if File.zero?(file)
|
107
|
+
File.open(file, 'r') do |file_stream|
|
108
|
+
first_line = file_stream.readline
|
109
|
+
if first_line.slice(0,1) == '>'
|
110
|
+
return TRUE
|
111
|
+
else
|
112
|
+
return FALSE
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# returns command than needs to be run to make db
|
119
|
+
def ask_make_db_command(file, type)
|
120
|
+
LOG.info("FASTA file: #{file}")
|
121
|
+
LOG.info("Fasta type: " + type.to_s)
|
122
|
+
|
123
|
+
response = ''
|
124
|
+
until response.match(/^[yn]$/i) do
|
125
|
+
LOG.info("Proceed? [y/n]: ")
|
126
|
+
response = STDIN.gets.chomp
|
127
|
+
end
|
128
|
+
|
129
|
+
if response.match(/y/i)
|
130
|
+
LOG.info("Enter a database title (or will use '#{File.basename(file)}'")
|
131
|
+
title = STDIN.gets.chomp
|
132
|
+
title.gsub!('"', "'")
|
133
|
+
title = File.basename(file) if title.empty?
|
134
|
+
|
135
|
+
return make_db_command(file,type,title)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def make_db_command(file,type, title)
|
140
|
+
LOG.info("Will make #{type.to_s} database from #{file} with #{title}")
|
141
|
+
command = %|#{@app.binaries['makeblastdb']} -in #{file} -dbtype #{ type.to_s.slice(0,4)} -title "#{title}" -parse_seqids|
|
142
|
+
LOG.info("Returning: #{command}")
|
143
|
+
return(command)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
OptionParser.new do |opts|
|
148
|
+
opts.banner =<<BANNER
|
149
|
+
NAME
|
150
|
+
|
151
|
+
database_formatter.rb - prepare BLAST databases for SequenceServer
|
152
|
+
|
153
|
+
SYNOPSIS
|
154
|
+
|
155
|
+
./database_formatter.rb [--verbose] [blast_database_directory]
|
156
|
+
|
157
|
+
Example:
|
158
|
+
|
159
|
+
$ ./database_formatter.rb ~/db # explicitly specify a database directory
|
160
|
+
$ ./database_formatter # use the database directory in config.yml
|
161
|
+
|
162
|
+
DESCRIPTION
|
163
|
+
|
164
|
+
database_formatter recursively scans the given 'blast_database_directory' for
|
165
|
+
BLAST databases and formats them for use with SequenceServer.
|
166
|
+
|
167
|
+
It automagically detects the database type, and ignores non-db files and
|
168
|
+
pre-formatted databases. The 'parse_seqids' makeblastdb options is used.
|
169
|
+
|
170
|
+
'blast_database_directory' can be passed as a command line parameter or
|
171
|
+
through config.yml by setting the 'database' key (the same option used by
|
172
|
+
SequenceServer). See example.config.yml. database_formatter will check
|
173
|
+
config.yml only if the command line parameter is missing.
|
174
|
+
|
175
|
+
Failing both, database_formatter will look for 'database' directory relative
|
176
|
+
to the current working directory i.e ./database.
|
177
|
+
|
178
|
+
database_formatter can be used standalone too.
|
179
|
+
|
180
|
+
OPTIONS
|
181
|
+
|
182
|
+
BANNER
|
183
|
+
|
184
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
185
|
+
puts opts
|
186
|
+
exit
|
187
|
+
end
|
188
|
+
|
189
|
+
opts.on('-v', '--verbose', 'Print lots of output') do
|
190
|
+
LOG.level = Logger::DEBUG
|
191
|
+
end
|
192
|
+
end.parse!
|
193
|
+
|
194
|
+
app = DatabaseFormatter.new(ARGV[0])
|
195
|
+
app.format_databases
|
data/bin/sequenceserver
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# application root
|
4
|
+
root = File.dirname(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.join(root, 'lib', 'sequenceserver')
|
8
|
+
|
9
|
+
# display name for tools like `ps`
|
10
|
+
$PROGRAM_NAME = 'sequenceserver'
|
11
|
+
|
12
|
+
SequenceServer::App.run!
|
data/config.ru
ADDED
data/example.config.yml
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Path to the blast executables.
|
2
|
+
#
|
3
|
+
# Sequence Server scans the given directory for blast binaries. Ideally it
|
4
|
+
# should point the `bin` of your BLAST+ installation. Not setting this
|
5
|
+
# value, or setting it to `nil` will default to searching the system `PATH`.
|
6
|
+
#
|
7
|
+
# Uncomment the following line, and change to appropriate value to use.
|
8
|
+
#
|
9
|
+
# bin: ~/ncbi-blast-2.2.25+/bin/
|
10
|
+
|
11
|
+
# Path to blast database.
|
12
|
+
#
|
13
|
+
# Sequence Server scans the given directory (including the sub-directories)
|
14
|
+
# for blast database. You can not specify more than one top-level directory.
|
15
|
+
# Not setting this value, will default to searching `database` directory
|
16
|
+
# relative to the current working directory.
|
17
|
+
#
|
18
|
+
# Uncomment the following line, and change to appropriate value to use.
|
19
|
+
#
|
20
|
+
# database: ~/blast_databases/
|
21
|
+
|
22
|
+
# Port to run Sequence Server on.
|
23
|
+
#
|
24
|
+
# The app will then be accessible at http://your-ip:port. Defaults to 4567.
|
25
|
+
# http://localhost:port is also valid for local access.
|
26
|
+
#
|
27
|
+
# Uncomment the following line, and change to appropriate value to use.
|
28
|
+
#
|
29
|
+
# port: 4567
|
30
|
+
|
31
|
+
# number of threads to be use when blasting
|
32
|
+
#
|
33
|
+
# This option is passed directly to BLAST+. Setting this option to more
|
34
|
+
# than 1 may crash BLAST+ if it was not compiled with threading support.
|
35
|
+
# Default is to use the safe value of 1.
|
36
|
+
#
|
37
|
+
# Uncomment the following line, and change to appropriate value to use.
|
38
|
+
#
|
39
|
+
# num_threads: 1
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module SequenceServer
|
5
|
+
# Simple ncbi-blast wrapper. Check examples below.
|
6
|
+
class Blast
|
7
|
+
# blast method
|
8
|
+
attr_accessor :method
|
9
|
+
|
10
|
+
# database name
|
11
|
+
attr_accessor :db
|
12
|
+
|
13
|
+
# query sequence string
|
14
|
+
attr_accessor :qstring
|
15
|
+
|
16
|
+
# query file name
|
17
|
+
attr_accessor :qfile
|
18
|
+
|
19
|
+
# advanced blast options
|
20
|
+
attr_accessor :options
|
21
|
+
|
22
|
+
# command string to be executed
|
23
|
+
attr_reader :command
|
24
|
+
|
25
|
+
# result of executing command
|
26
|
+
attr_reader :result
|
27
|
+
|
28
|
+
# blast archive file output
|
29
|
+
attr_reader :blast_archive_tempfile
|
30
|
+
|
31
|
+
# errors if any while executing command
|
32
|
+
attr_reader :error
|
33
|
+
|
34
|
+
# Initialize a new blast search.
|
35
|
+
# ---
|
36
|
+
# Arguments(optional):
|
37
|
+
# * method(String) - blast executable (shell executable, or absolute path)
|
38
|
+
# * db(String) - database name as returned by 'blastdbcmd -list'
|
39
|
+
# * query(Hash) - query string/file, and options.
|
40
|
+
#
|
41
|
+
# In the query Hash, use:
|
42
|
+
# * :qfile(String) - to run Blast against a file.
|
43
|
+
# * :qstrin(String) - to run Blast against a string.
|
44
|
+
# * :options(String) - to specify multiple blast options.
|
45
|
+
#
|
46
|
+
# Either :qfile, or :qstring should be used. If both are given, by design
|
47
|
+
# :qstring will be used to run blast.
|
48
|
+
# ---
|
49
|
+
# Examples:
|
50
|
+
#
|
51
|
+
# b = Blast.new("blastn", "S.cdna.fasta", :qfile => 'query.seq', :options => "-html -num_threads 4")
|
52
|
+
# b = Blast.new("blastn", "S.cdna.fasta", :qstring => 'ATGTCCGCGAATCGATTGAACGTGCTGGTGACCCTGATGCTCGCCGTCGCGCTTCTTGTG')
|
53
|
+
#
|
54
|
+
# b.run! => true
|
55
|
+
# b.result => "blast output"
|
56
|
+
#
|
57
|
+
# # change the blast method.
|
58
|
+
# b.method = 'blastp'
|
59
|
+
#
|
60
|
+
# b.run! => false
|
61
|
+
# b.error => "blast error output"
|
62
|
+
def initialize(method = nil, db = nil, query = {})
|
63
|
+
@method = method
|
64
|
+
@db = db
|
65
|
+
@qstring = query[:qstring]
|
66
|
+
@qfile = query[:qfile]
|
67
|
+
@options = query[:options]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Run blast everytime it is called. Returns the success
|
71
|
+
# status - true, or false. Blast method, db, and qfile/qstring
|
72
|
+
# need to be set before calling this method, else blast will fail.
|
73
|
+
#
|
74
|
+
# b = Blast.new
|
75
|
+
# b.run! => false
|
76
|
+
#
|
77
|
+
# # set blast method, and db
|
78
|
+
# b.method = 'blastn'
|
79
|
+
# b.db = 'S.cdna.fasta'
|
80
|
+
#
|
81
|
+
# b.run! => false
|
82
|
+
# b.errors => "blast error output"
|
83
|
+
#
|
84
|
+
# # set qfile
|
85
|
+
# b.qfile = 'query1.seq'
|
86
|
+
#
|
87
|
+
# b.run! => true
|
88
|
+
# b.reuslt => "blast output"
|
89
|
+
def run!
|
90
|
+
# can not run blast if method is not specified
|
91
|
+
return false unless @method
|
92
|
+
|
93
|
+
# create a tempfile if qstring is given
|
94
|
+
if @qstring
|
95
|
+
@tempfile = Tempfile.new('qfile')
|
96
|
+
@tempfile.puts(qstring)
|
97
|
+
@tempfile.close
|
98
|
+
@qfile = @tempfile.path
|
99
|
+
end
|
100
|
+
|
101
|
+
# form command to execute
|
102
|
+
@command = to_s
|
103
|
+
|
104
|
+
# execute command and capture both stdout, and stderr
|
105
|
+
Open3.popen3(@command) do |stdin, stdout, stderr|
|
106
|
+
@result = stdout.readlines # convert to string?
|
107
|
+
@error = stderr.readlines
|
108
|
+
end
|
109
|
+
|
110
|
+
# set and return success status
|
111
|
+
return @success = @error.empty?
|
112
|
+
|
113
|
+
ensure
|
114
|
+
# delete tempfile if it was created
|
115
|
+
@tempfile.unlink if @tempfile
|
116
|
+
end
|
117
|
+
|
118
|
+
# Return the blast type used as a String.
|
119
|
+
#
|
120
|
+
# b.method = '/home/yeban/opt/blastn'
|
121
|
+
# b.type => 'blastn'
|
122
|
+
def type
|
123
|
+
@type ||= @method[(@method.rindex('/') + 1)..-1]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Return success status - true, false, or nil.
|
127
|
+
# 'nil' implies that blast has not been run yet.
|
128
|
+
def success?
|
129
|
+
@success
|
130
|
+
end
|
131
|
+
|
132
|
+
# String representation of the blast object - same as
|
133
|
+
# the command to be executed.
|
134
|
+
def to_s
|
135
|
+
s = "#@method "
|
136
|
+
s << "-db '#@db' " if @db
|
137
|
+
s << "-query #@qfile " if @qfile
|
138
|
+
s << @options.to_s if @options
|
139
|
+
s
|
140
|
+
end
|
141
|
+
|
142
|
+
# Especially helpful in irb - "status : command"
|
143
|
+
def inspect
|
144
|
+
return to_s if success?.nil?
|
145
|
+
(success? ? "success : " : "fail : ") + @command
|
146
|
+
end
|
147
|
+
|
148
|
+
# Run the blast with the options specified by the user, returning a blast archive file, which can be further transformed into other formats
|
149
|
+
def run_to_blast_archive!
|
150
|
+
@blast_archive_tempfile = Tempfile.open('seqserve_formatter')
|
151
|
+
|
152
|
+
# Add -outfmt 11 to list of options so that it outputs a blast archive
|
153
|
+
@options ||= ''
|
154
|
+
@options += " -outfmt 11 -out #{@blast_archive_tempfile.path}"
|
155
|
+
|
156
|
+
# Run the blast
|
157
|
+
run!
|
158
|
+
return @success unless @success
|
159
|
+
end
|
160
|
+
|
161
|
+
# convert the blast archive to a regular HTML result, stored
|
162
|
+
# as an instance variable Blast#result
|
163
|
+
def convert_blast_archive_to_html_result(blast_formatter_path)
|
164
|
+
@command = "#{blast_formatter_path} -archive #{blast_archive_tempfile.path} -html"
|
165
|
+
|
166
|
+
# execute command and capture both stdout, and stderr
|
167
|
+
Open3.popen3(@command) do |stdin, stdout, stderr|
|
168
|
+
@result = stdout.readlines # convert to string?
|
169
|
+
@error = stderr.readlines
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class << self
|
174
|
+
# shortcut method to run blast against a query file
|
175
|
+
def blast_file(method, db, qfile, options = nil)
|
176
|
+
b = Blast.new(method, db, :qfile => qfile, :options => options)
|
177
|
+
b.run!
|
178
|
+
b
|
179
|
+
end
|
180
|
+
|
181
|
+
# shortcut method to run blast against a query string
|
182
|
+
def blast_string(method, db, qstring, options = nil)
|
183
|
+
b = Blast.new(method, db, :qstring => qstring, :options => options)
|
184
|
+
b.run!
|
185
|
+
b
|
186
|
+
end
|
187
|
+
|
188
|
+
# shortcut method to run blast with a query string and return a
|
189
|
+
# blast archive, which can then be further processed into other useful
|
190
|
+
# output forms (e.g. HTML, GFF). If it ran successfully, the blast archive
|
191
|
+
# is a Tempfile accessible as an instance variable of the returned
|
192
|
+
# Blast object.
|
193
|
+
def blast_string_to_blast_archive(method, db, qstring, options = nil)
|
194
|
+
b = Blast.new(method, db, :qstring => qstring, :options => options)
|
195
|
+
b.run_to_blast_archive!
|
196
|
+
b
|
197
|
+
end
|
198
|
+
|
199
|
+
# shortcut method to run blast with a query string and return a
|
200
|
+
# blast archive, which can then be further processed into other useful
|
201
|
+
# output forms (e.g. HTML, GFF). If it ran successfully, the blast archive
|
202
|
+
# is a Tempfile accessible as an instance variable of the returned
|
203
|
+
# Blast object.
|
204
|
+
def blast_string_to_blast_archive(method, db, qstring, options = nil)
|
205
|
+
b = Blast.new(method, db, :qstring => qstring, :options => options)
|
206
|
+
b.run_to_blast_archive!
|
207
|
+
b
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SequenceServer
|
2
|
+
module Customisation
|
3
|
+
## When not commented out, this method is used to take a
|
4
|
+
## sequence ID, and return a hyperlink that
|
5
|
+
## replaces the hit in the BLAST output.
|
6
|
+
##
|
7
|
+
## Return the hyperlink to link to, or nil
|
8
|
+
## to not not include a hyperlink.
|
9
|
+
##
|
10
|
+
## When this method
|
11
|
+
## is commented out, the default link is used. The default
|
12
|
+
## is a link to the full sequence of
|
13
|
+
## the hit is displayed (if makeblastdb has been run with
|
14
|
+
## -parse_seqids), or no link at all otherwise.
|
15
|
+
# def construct_custom_sequence_hyperlink(options)
|
16
|
+
# ## Example:
|
17
|
+
# ## sequence_id comes in like "psu|MAL13P1.200 | organism=Plasmodium_falciparum_3D7 | product=mitochondrial"
|
18
|
+
# ## output: "http://apiloc.bio21.unimelb.edu.au/apiloc/gene/MAL13P1.200"
|
19
|
+
# matches = options[:sequence_id].match(/^\s*psu\|(\S+) /)
|
20
|
+
# if matches #if the sequence_id conforms to our expectations
|
21
|
+
# # All is good. Return the hyperlink.
|
22
|
+
# return "http://apiloc.bio21.unimelb.edu.au/apiloc/gene/#{matches[1]}"
|
23
|
+
# else
|
24
|
+
# # Parsing the sequence_id didn't work. Don't include a hyperlink for this
|
25
|
+
# # sequence_id, but log that there has been a problem.
|
26
|
+
# settings.log.warn "Unable to parse sequence id `#{options[:sequence_id]}'"
|
27
|
+
# # Return nil so no hyperlink is generated.
|
28
|
+
# return nil
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
|
32
|
+
## Much like construct_custom_sequence_hyperlink, except
|
33
|
+
## instead of just a hyperlink being defined, the whole
|
34
|
+
## line as it appears in the blast results is generated.
|
35
|
+
##
|
36
|
+
## This is a therefore more flexible setup than is possible
|
37
|
+
## with construct_custom_sequence_hyperlink, because doing
|
38
|
+
## things such as adding two hyperlinks for the one hit
|
39
|
+
## are possible.
|
40
|
+
##
|
41
|
+
## When this method is commented out, the behaviour is that
|
42
|
+
## the construct_custom_sequence_hyperlink method is used,
|
43
|
+
## or failing that the default method of that is used.
|
44
|
+
# def construct_custom_sequence_hyperlinking_line(options)
|
45
|
+
# matches = options[:sequence_id].match(/^\s*psu\|(\S+) /)
|
46
|
+
# if matches #if the sequence_id conforms to our expectations
|
47
|
+
# # All is good. Return the hyperlink.
|
48
|
+
# link1 = "http://apiloc.bio21.unimelb.edu.au/apiloc/gene/#{matches[1]}"
|
49
|
+
# link2 = "http://google.com/?q=#{matches[1]}"
|
50
|
+
# return "<a href='#{link1}'>ApiLoc page</a>, <a href='#{link2}'>Google search</a>"
|
51
|
+
# else
|
52
|
+
# # Parsing the sequence_id didn't work. Don't include a hyperlink for this
|
53
|
+
# # sequence_id, but log that there has been a problem.
|
54
|
+
# settings.log.warn "Unable to parse sequence id `#{options[:sequence_id]}'"
|
55
|
+
# # Return nil so no hyperlink is generated.
|
56
|
+
# return nil
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SequenceServer
|
2
|
+
class Database < Struct.new("Database", :name, :title)
|
3
|
+
def to_s
|
4
|
+
"#{title} #{name}"
|
5
|
+
end
|
6
|
+
|
7
|
+
# Its not very meaningful to compare Database objects, however,
|
8
|
+
# we still add the 'spaceship' operator to be able to sort the
|
9
|
+
# databases by 'title', or 'name' for better visual presentation.
|
10
|
+
#
|
11
|
+
# We use 'title' for comparison, while relying on 'name' as fallback.
|
12
|
+
#
|
13
|
+
# Trying to sort a list of dbs with 'title' set only for some of them
|
14
|
+
# will obviously produce unpredictable sorting order.
|
15
|
+
def <=>(other)
|
16
|
+
if self.title and other.title
|
17
|
+
self.title <=> other.title
|
18
|
+
else
|
19
|
+
self.name <=> other.name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|