quorum 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +170 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +318 -0
- data/Rakefile +31 -0
- data/app/assets/images/quorum/.gitkeep +0 -0
- data/app/assets/images/quorum/bg.png +0 -0
- data/app/assets/images/quorum/knight_rider.gif +0 -0
- data/app/assets/images/quorum/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/app/assets/images/quorum/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/app/assets/images/quorum/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/app/assets/images/quorum/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/app/assets/images/quorum/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/app/assets/images/quorum/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/app/assets/images/quorum/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/app/assets/images/quorum/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
- data/app/assets/images/quorum/ui-icons_222222_256x240.png +0 -0
- data/app/assets/images/quorum/ui-icons_2e83ff_256x240.png +0 -0
- data/app/assets/images/quorum/ui-icons_454545_256x240.png +0 -0
- data/app/assets/images/quorum/ui-icons_888888_256x240.png +0 -0
- data/app/assets/images/quorum/ui-icons_cd0a0a_256x240.png +0 -0
- data/app/assets/javascripts/quorum/application.js +13 -0
- data/app/assets/javascripts/quorum/jobs.js +386 -0
- data/app/assets/stylesheets/quorum/application.css +224 -0
- data/app/assets/stylesheets/quorum/jobs.css +72 -0
- data/app/assets/stylesheets/quorum/jquery-ui-1.8.16.custom.css +568 -0
- data/app/assets/stylesheets/quorum/tipsy.css +25 -0
- data/app/controllers/quorum/application_controller.rb +5 -0
- data/app/controllers/quorum/jobs_controller.rb +102 -0
- data/app/helpers/quorum/application_helper.rb +4 -0
- data/app/models/quorum/blastn_job.rb +111 -0
- data/app/models/quorum/blastn_job_report.rb +7 -0
- data/app/models/quorum/blastp_job.rb +111 -0
- data/app/models/quorum/blastp_job_report.rb +7 -0
- data/app/models/quorum/blastx_job.rb +111 -0
- data/app/models/quorum/blastx_job_report.rb +7 -0
- data/app/models/quorum/job.rb +164 -0
- data/app/models/quorum/tblastn_job.rb +111 -0
- data/app/models/quorum/tblastn_job_report.rb +7 -0
- data/app/views/layouts/quorum/application.html.erb +15 -0
- data/app/views/quorum/jobs/_blastn_form.html.erb +71 -0
- data/app/views/quorum/jobs/_blastp_form.html.erb +71 -0
- data/app/views/quorum/jobs/_blastx_form.html.erb +71 -0
- data/app/views/quorum/jobs/_tblastn_form.html.erb +71 -0
- data/app/views/quorum/jobs/new.html.erb +45 -0
- data/app/views/quorum/jobs/show.html.erb +183 -0
- data/app/views/shared/_error_messages.html.erb +10 -0
- data/config/locales/en.yml +8 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20111031204518_create_jobs.rb +12 -0
- data/db/migrate/20111031204701_create_blastn_jobs.rb +19 -0
- data/db/migrate/20111031204719_create_blastx_jobs.rb +19 -0
- data/db/migrate/20111031204733_create_blastp_jobs.rb +19 -0
- data/db/migrate/20111031204754_create_tblastn_jobs.rb +19 -0
- data/db/migrate/20111031204846_create_blastn_job_reports.rb +34 -0
- data/db/migrate/20111031204903_create_blastx_job_reports.rb +34 -0
- data/db/migrate/20111031204922_create_blastp_job_reports.rb +34 -0
- data/db/migrate/20111031204941_create_tblastn_job_reports.rb +34 -0
- data/lib/generators/quorum/install_generator.rb +68 -0
- data/lib/generators/quorum/styles_generator.rb +18 -0
- data/lib/generators/quorum/views_generator.rb +18 -0
- data/lib/generators/templates/README +25 -0
- data/lib/generators/templates/blast.rb +412 -0
- data/lib/generators/templates/logger.rb +43 -0
- data/lib/generators/templates/quorum_initializer.rb +36 -0
- data/lib/generators/templates/quorum_settings.yml +157 -0
- data/lib/generators/templates/search +141 -0
- data/lib/generators/templates/trollop.rb +781 -0
- data/lib/quorum/engine.rb +5 -0
- data/lib/quorum/helpers.rb +17 -0
- data/lib/quorum/sequence.rb +89 -0
- data/lib/quorum/version.rb +3 -0
- data/lib/quorum.rb +89 -0
- data/lib/tasks/blastdb/README +17 -0
- data/lib/tasks/blastdb/build_blast_db.rb +222 -0
- data/lib/tasks/quorum_resque.rake +3 -0
- data/lib/tasks/quorum_tasks.rake +50 -0
- data/lib/workers/quorum.rb +45 -0
- data/quorum.gemspec +29 -0
- data/script/rails +6 -0
- data/spec/data/nucl_prot_seqs.txt +36 -0
- data/spec/data/nucl_seqs.txt +32 -0
- data/spec/data/prot_seqs.txt +4 -0
- data/spec/data/seqs.docx +0 -0
- data/spec/data/seqs_not_fa.txt +16 -0
- data/spec/data/tmp/test.tgz +0 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/blast.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +46 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/environment.rb +20 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/quorum_initializer.rb +36 -0
- data/spec/dummy/config/initializers/resque.rb +1 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/locales/quorum.en.yml +8 -0
- data/spec/dummy/config/quorum_settings.yml +145 -0
- data/spec/dummy/config/routes.rb +9 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +214 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/quorum/bin/search +141 -0
- data/spec/dummy/quorum/blastdb/test/contigs.fa +2 -0
- data/spec/dummy/quorum/blastdb/test/peptides.fa +2 -0
- data/spec/dummy/quorum/blastdb/test.nhd +1 -0
- data/spec/dummy/quorum/blastdb/test.nhi +0 -0
- data/spec/dummy/quorum/blastdb/test.nhr +0 -0
- data/spec/dummy/quorum/blastdb/test.nin +0 -0
- data/spec/dummy/quorum/blastdb/test.nog +0 -0
- data/spec/dummy/quorum/blastdb/test.nsd +1 -0
- data/spec/dummy/quorum/blastdb/test.nsi +0 -0
- data/spec/dummy/quorum/blastdb/test.nsq +0 -0
- data/spec/dummy/quorum/blastdb/test.phd +1 -0
- data/spec/dummy/quorum/blastdb/test.phi +0 -0
- data/spec/dummy/quorum/blastdb/test.phr +0 -0
- data/spec/dummy/quorum/blastdb/test.pin +0 -0
- data/spec/dummy/quorum/blastdb/test.pog +0 -0
- data/spec/dummy/quorum/blastdb/test.psd +1 -0
- data/spec/dummy/quorum/blastdb/test.psi +0 -0
- data/spec/dummy/quorum/blastdb/test.psq +0 -0
- data/spec/dummy/quorum/lib/logger.rb +43 -0
- data/spec/dummy/quorum/lib/search_tools/blast.rb +412 -0
- data/spec/dummy/quorum/lib/trollop.rb +781 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/models/blastn_job_report_spec.rb +13 -0
- data/spec/models/blastn_job_spec.rb +103 -0
- data/spec/models/blastp_job_report_spec.rb +13 -0
- data/spec/models/blastp_job_spec.rb +103 -0
- data/spec/models/blastx_job_report_spec.rb +13 -0
- data/spec/models/blastx_job_spec.rb +103 -0
- data/spec/models/job_spec.rb +40 -0
- data/spec/models/tblastn_job_report_spec.rb +13 -0
- data/spec/models/tblastn_job_spec.rb +103 -0
- data/spec/quorum/quorum_sequence_spec.rb +64 -0
- data/spec/quorum_installed_spec.rb +64 -0
- data/spec/requests/jobs_spec.rb +138 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/tasks/blastdb_rake_spec.rb +119 -0
- data/spec/templates/blast_spec.rb +8 -0
- data/spec/templates/logger_spec.rb +35 -0
- data/vendor/assets/javascripts/jquery.tipsy.js +241 -0
- data/vendor/assets/javascripts/underscore-min.js +30 -0
- metadata +325 -0
@@ -0,0 +1,412 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path("../../", __FILE__))
|
2
|
+
|
3
|
+
require 'bio-blastxmlparser'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
module Quorum
|
7
|
+
module SearchTools
|
8
|
+
#
|
9
|
+
# Blast Search Tool
|
10
|
+
#
|
11
|
+
class Blast
|
12
|
+
|
13
|
+
class QuorumJob < ActiveRecord::Base
|
14
|
+
has_one :quorum_blastn_job,
|
15
|
+
:foreign_key => "job_id"
|
16
|
+
has_many :quorum_blastn_job_reports,
|
17
|
+
:foreign_key => "blastn_job_id"
|
18
|
+
|
19
|
+
has_one :quorum_blastx_job,
|
20
|
+
:foreign_key => "job_id"
|
21
|
+
has_many :quorum_blastx_job_reports,
|
22
|
+
:foreign_key => "blastx_job_id"
|
23
|
+
|
24
|
+
has_one :quorum_tblastn_job,
|
25
|
+
:foreign_key => "job_id"
|
26
|
+
has_many :quorum_tblastn_job_reports,
|
27
|
+
:foreign_key => "tblastn_job_id"
|
28
|
+
|
29
|
+
has_one :quorum_blastp_job,
|
30
|
+
:foreign_key => "job_id"
|
31
|
+
has_many :quorum_blastp_job_reports,
|
32
|
+
:foreign_key => "blastp_job_id"
|
33
|
+
end
|
34
|
+
|
35
|
+
class QuorumBlastnJob < ActiveRecord::Base
|
36
|
+
belongs_to :quorum_job
|
37
|
+
has_many :quorum_blastn_job_reports
|
38
|
+
end
|
39
|
+
|
40
|
+
class QuorumBlastnJobReport < ActiveRecord::Base
|
41
|
+
belongs_to :quorum_blastn_job
|
42
|
+
end
|
43
|
+
|
44
|
+
class QuorumBlastxJob < ActiveRecord::Base
|
45
|
+
belongs_to :quorum_job
|
46
|
+
has_many :quorum_blastx_job_reports
|
47
|
+
end
|
48
|
+
|
49
|
+
class QuorumBlastxJobReport < ActiveRecord::Base
|
50
|
+
belongs_to :quorum_blastx_job
|
51
|
+
end
|
52
|
+
|
53
|
+
class QuorumTblastnJob < ActiveRecord::Base
|
54
|
+
belongs_to :quorum_job
|
55
|
+
has_many :quorum_tblastn_job_reports
|
56
|
+
end
|
57
|
+
|
58
|
+
class QuorumTblastnJobReport < ActiveRecord::Base
|
59
|
+
belongs_to :quorum_tblastn_job
|
60
|
+
end
|
61
|
+
|
62
|
+
class QuorumBlastpJob < ActiveRecord::Base
|
63
|
+
belongs_to :quorum_job
|
64
|
+
has_many :quorum_blastp_job_reports
|
65
|
+
end
|
66
|
+
|
67
|
+
class QuorumBlastpJobReport < ActiveRecord::Base
|
68
|
+
belongs_to :quorum_blastp_job
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def initialize(args)
|
74
|
+
@algorithm = args[:search_tool]
|
75
|
+
@id = args[:id]
|
76
|
+
@log_directory = args[:log_directory]
|
77
|
+
@tmp = args[:tmp_directory]
|
78
|
+
@search_database = args[:search_database]
|
79
|
+
@threads = args[:threads]
|
80
|
+
|
81
|
+
@logger = Quorum::Logger.new(@log_directory)
|
82
|
+
|
83
|
+
begin
|
84
|
+
@job = QuorumJob.find(@id)
|
85
|
+
rescue Exception => e
|
86
|
+
@logger.log("ActiveRecord", e.message, 1)
|
87
|
+
end
|
88
|
+
|
89
|
+
@na_sequence = @job.na_sequence
|
90
|
+
@aa_sequence = @job.aa_sequence
|
91
|
+
|
92
|
+
## Create for method invocation ##
|
93
|
+
@job_association = "quorum_#{@algorithm}_job".to_sym
|
94
|
+
@job_report_association = "quorum_#{@algorithm}_job_reports".to_sym
|
95
|
+
|
96
|
+
@filter = @job.method(@job_association).call.filter
|
97
|
+
@expectation = @job.method(@job_association).call.expectation
|
98
|
+
@max_score = @job.method(@job_association).call.max_score
|
99
|
+
@min_score = @job.method(@job_association).call.min_bit_score
|
100
|
+
@gapped_alignments = @job.method(@job_association).call.gapped_alignments
|
101
|
+
@gap_opening_penalty = @job.method(@job_association).call.gap_opening_penalty
|
102
|
+
@gap_extension_penalty = @job.method(@job_association).call.gap_extension_penalty
|
103
|
+
|
104
|
+
@db = @job.method(@job_association).call.blast_dbs.split(';')
|
105
|
+
@db.map! { |d| File.join(@search_database, d) }
|
106
|
+
@db = @db.join(' ')
|
107
|
+
|
108
|
+
@hash = create_hash(@job.sequence)
|
109
|
+
@tmp_files = File.join(@tmp, @hash) << "*"
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Create a unique hash plus timestamp.
|
114
|
+
#
|
115
|
+
def create_hash(sequence)
|
116
|
+
Digest::MD5.hexdigest(sequence).to_s + "-" + Time.now.to_f.to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
def generate_blastn_cmd
|
120
|
+
blastn = "blastn " <<
|
121
|
+
"-db \"#{@db}\" " <<
|
122
|
+
"-query #{@na_fasta} " <<
|
123
|
+
"-outfmt 5 " <<
|
124
|
+
"-num_threads #{@threads} " <<
|
125
|
+
"-evalue #{@expectation} " <<
|
126
|
+
"-max_target_seqs #{@max_score} " <<
|
127
|
+
"-out #{@out} "
|
128
|
+
if @gapped_alignments
|
129
|
+
blastn << "-gapopen #{@gap_opening_penalty} "
|
130
|
+
blastn << "-gapextend #{@gap_extension_penalty} "
|
131
|
+
else
|
132
|
+
blastn << "-ungapped "
|
133
|
+
end
|
134
|
+
blastn << "-dust yes " if @filter
|
135
|
+
blastn
|
136
|
+
end
|
137
|
+
|
138
|
+
def generate_blastx_cmd
|
139
|
+
blastx = "blastx " <<
|
140
|
+
"-db \"#{@db}\" " <<
|
141
|
+
"-query #{@na_fasta} " <<
|
142
|
+
"-outfmt 5 " <<
|
143
|
+
"-num_threads #{@threads} " <<
|
144
|
+
"-evalue #{@expectation} " <<
|
145
|
+
"-max_target_seqs #{@max_score} " <<
|
146
|
+
"-out #{@out} "
|
147
|
+
if @gapped_alignments
|
148
|
+
blastx << "-gapopen #{@gap_opening_penalty} "
|
149
|
+
blastx << "-gapextend #{@gap_extension_penalty} "
|
150
|
+
else
|
151
|
+
blastx << "-ungapped "
|
152
|
+
end
|
153
|
+
blastx << "-seg yes " if @filter
|
154
|
+
blastx
|
155
|
+
end
|
156
|
+
|
157
|
+
def generate_tblastn_cmd
|
158
|
+
tblastn = "tblastn " <<
|
159
|
+
"-db \"#{@db}\" " <<
|
160
|
+
"-query #{@aa_fasta} " <<
|
161
|
+
"-outfmt 5 " <<
|
162
|
+
"-num_threads #{@threads} " <<
|
163
|
+
"-evalue #{@expectation} " <<
|
164
|
+
"-max_target_seqs #{@max_score} " <<
|
165
|
+
"-out #{@out} "
|
166
|
+
if @gapped_alignments
|
167
|
+
tblastn << "-gapopen #{@gap_opening_penalty} "
|
168
|
+
tblastn << "-gapextend #{@gap_extension_penalty} "
|
169
|
+
tblastn << "-comp_based_stats D "
|
170
|
+
else
|
171
|
+
tblastn << "-ungapped "
|
172
|
+
tblastn << "-comp_based_stats F "
|
173
|
+
end
|
174
|
+
tblastn << "-seg yes " if @filter
|
175
|
+
tblastn
|
176
|
+
end
|
177
|
+
|
178
|
+
def generate_blastp_cmd
|
179
|
+
blastp = "blastp " <<
|
180
|
+
"-db \"#{@db}\" " <<
|
181
|
+
"-query #{@aa_fasta} " <<
|
182
|
+
"-outfmt 5 " <<
|
183
|
+
"-num_threads #{@threads} " <<
|
184
|
+
"-evalue #{@expectation} " <<
|
185
|
+
"-max_target_seqs #{@max_score} " <<
|
186
|
+
"-out #{@out} "
|
187
|
+
if @gapped_alignments
|
188
|
+
blastp << "-gapopen #{@gap_opening_penalty} "
|
189
|
+
blastp << "-gapextend #{@gap_extension_penalty} "
|
190
|
+
blastp << "-comp_based_stats D "
|
191
|
+
else
|
192
|
+
blastp << "-ungapped "
|
193
|
+
blastp << "-comp_based_stats F "
|
194
|
+
end
|
195
|
+
blastp << "-seg yes " if @filter
|
196
|
+
blastp
|
197
|
+
end
|
198
|
+
|
199
|
+
#
|
200
|
+
# Generate Blast Command
|
201
|
+
#
|
202
|
+
def generate_blast_cmd
|
203
|
+
@cmd = ""
|
204
|
+
|
205
|
+
@na_fasta = File.join(@tmp, @hash + ".na.fa")
|
206
|
+
@aa_fasta = File.join(@tmp, @hash + ".aa.fa")
|
207
|
+
File.open(@na_fasta, "w") { |f| f << @na_sequence }
|
208
|
+
File.open(@aa_fasta, "w") { |f| f << @aa_sequence }
|
209
|
+
|
210
|
+
@out = File.join(@tmp, @hash + ".out.xml")
|
211
|
+
File.new(@out, "w")
|
212
|
+
|
213
|
+
case @algorithm
|
214
|
+
when "blastn"
|
215
|
+
@cmd << generate_blastn_cmd
|
216
|
+
when "blastx"
|
217
|
+
@cmd << generate_blastx_cmd
|
218
|
+
when "tblastn"
|
219
|
+
@cmd << generate_tblastn_cmd
|
220
|
+
when "blastp"
|
221
|
+
@cmd << generate_blastp_cmd
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
#
|
226
|
+
# Make the E-value look pretty.
|
227
|
+
#
|
228
|
+
def format_evalue(evalue)
|
229
|
+
evalue = evalue.to_s
|
230
|
+
e = evalue.slice!(/e.*/)
|
231
|
+
unless e.nil?
|
232
|
+
e = " x 10<sup>" << e.sub(/e/, '') << "</sup>"
|
233
|
+
end
|
234
|
+
evalue.to_f.round(1).to_s << e.to_s
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# Format Blast report hit_id and hit_def.
|
239
|
+
#
|
240
|
+
# For added flexibility, Quorum doesn't parse seqids or deflines.
|
241
|
+
# Instead, format_hit splits the hit_def on whitespace and
|
242
|
+
# reports hit_id as the first element and hit_def as the second.
|
243
|
+
#
|
244
|
+
def format_hit(str)
|
245
|
+
hit_id = ""
|
246
|
+
hit_def = ""
|
247
|
+
|
248
|
+
hit = str.split(" ", 2)
|
249
|
+
if hit.length < 2
|
250
|
+
hit_id = hit.first
|
251
|
+
hit_def = "None"
|
252
|
+
else
|
253
|
+
hit_id = hit.first
|
254
|
+
hit_def = hit.last
|
255
|
+
end
|
256
|
+
|
257
|
+
return hit_id, hit_def
|
258
|
+
end
|
259
|
+
|
260
|
+
#
|
261
|
+
# Parse and save Blast results using bio-blastxmlparser.
|
262
|
+
# Only save Blast results if results.bit_score > @min_score.
|
263
|
+
#
|
264
|
+
def parse_and_save_results
|
265
|
+
# Helper to avoid having to perform a query.
|
266
|
+
saved = false
|
267
|
+
|
268
|
+
if File.size(@out) > 0
|
269
|
+
report = Bio::Blast::XmlIterator.new(@out)
|
270
|
+
report.to_enum.each do |iteration|
|
271
|
+
|
272
|
+
@data = {}
|
273
|
+
|
274
|
+
@data[:query] = iteration.query_def.split(" ").first
|
275
|
+
@data[:query_len] = iteration.query_len
|
276
|
+
|
277
|
+
iteration.each do |hit|
|
278
|
+
@data[:hit_id], @data[:hit_def] = format_hit(hit.hit_def)
|
279
|
+
|
280
|
+
@data[:hit_accession] = hit.accession
|
281
|
+
@data[:hit_len] = hit.len
|
282
|
+
|
283
|
+
hit.each do |hsp|
|
284
|
+
@data[:hsp_num] = hsp.hsp_num
|
285
|
+
@data[:bit_score] = hsp.bit_score
|
286
|
+
@data[:score] = hsp.score
|
287
|
+
@data[:evalue] = format_evalue(hsp.evalue)
|
288
|
+
@data[:query_from] = hsp.query_from
|
289
|
+
@data[:query_to] = hsp.query_to
|
290
|
+
@data[:hit_from] = hsp.hit_from
|
291
|
+
@data[:hit_to] = hsp.hit_to
|
292
|
+
@data[:query_frame] = hsp.query_frame
|
293
|
+
@data[:hit_frame] = hsp.hit_frame
|
294
|
+
@data[:identity] = hsp.identity
|
295
|
+
@data[:positive] = hsp.positive
|
296
|
+
@data[:align_len] = hsp.align_len
|
297
|
+
@data[:qseq] = hsp.qseq
|
298
|
+
@data[:hseq] = hsp.hseq
|
299
|
+
@data[:midline] = hsp.midline
|
300
|
+
|
301
|
+
# Hsps are only reported if a query hit against the Blast db.
|
302
|
+
# Only save the @data if bit_score exists.
|
303
|
+
if @data[:bit_score] &&
|
304
|
+
(@data[:bit_score].to_i > @min_score.to_i)
|
305
|
+
@data[:results] = true
|
306
|
+
@data["#{@algorithm}_job_id".to_sym] = @job.method(@job_association).call.job_id
|
307
|
+
saved = true
|
308
|
+
# Build a new report for each Hsp.
|
309
|
+
job_report = @job.method(@job_report_association).call.build(@data)
|
310
|
+
unless job_report.save!
|
311
|
+
@logger.log(
|
312
|
+
"ActiveRecord",
|
313
|
+
"Unable to save #{@algorithm} results to database.",
|
314
|
+
1,
|
315
|
+
@tmp_files
|
316
|
+
)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Save the record and set results to false.
|
326
|
+
unless saved
|
327
|
+
job_report = @job.method(@job_report_association).call.build(
|
328
|
+
"#{@algorithm}_job_id" => @job.method(@job_association).call.job_id,
|
329
|
+
"results" => false
|
330
|
+
)
|
331
|
+
unless job_report.save!
|
332
|
+
@logger.log(
|
333
|
+
"ActiveRecord",
|
334
|
+
"Unable to save #{@algorithm} results to database.",
|
335
|
+
1,
|
336
|
+
@tmp_files
|
337
|
+
)
|
338
|
+
end
|
339
|
+
@logger.log(
|
340
|
+
"NCBI Blast",
|
341
|
+
"#{@algorithm} report empty.",
|
342
|
+
0,
|
343
|
+
@tmp_files
|
344
|
+
)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
#
|
349
|
+
# Group record ids of hsps belonging to the same query and hit_accession.
|
350
|
+
#
|
351
|
+
def add_hps_groups_to_reports
|
352
|
+
groups = {}
|
353
|
+
|
354
|
+
query_hit_acc = @job.method(
|
355
|
+
@job_report_association
|
356
|
+
).call.select("DISTINCT query, hit_accession")
|
357
|
+
|
358
|
+
# Populate the hash of hashes with correct query and hit_accession.
|
359
|
+
query_hit_acc.each do |q|
|
360
|
+
groups[q.query] = {}
|
361
|
+
end
|
362
|
+
query_hit_acc.each do |q|
|
363
|
+
groups[q.query][q.hit_accession] = []
|
364
|
+
end
|
365
|
+
|
366
|
+
# Group record ids.
|
367
|
+
reports = @job.method(@job_report_association).call.order("id ASC")
|
368
|
+
reports.each do |r|
|
369
|
+
if groups[r.query][r.hit_accession]
|
370
|
+
groups[r.query][r.hit_accession] << r.id
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# Save hsp_group as a comma delimited string.
|
375
|
+
reports.each do |r|
|
376
|
+
if groups[r.query][r.hit_accession]
|
377
|
+
if groups[r.query][r.hit_accession].length > 1
|
378
|
+
r.hsp_group = groups[r.query][r.hit_accession].join(",")
|
379
|
+
unless r.save!
|
380
|
+
@logger.log(
|
381
|
+
"ActiveRecord",
|
382
|
+
"Unable to save #{@algorithm} results to database.",
|
383
|
+
1,
|
384
|
+
@tmp_files
|
385
|
+
)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def remove_tmp_files
|
393
|
+
`rm #{@tmp_files}` if @tmp_files
|
394
|
+
end
|
395
|
+
|
396
|
+
public
|
397
|
+
|
398
|
+
#
|
399
|
+
# Execute Blast on a given dataset.
|
400
|
+
#
|
401
|
+
def execute_blast
|
402
|
+
generate_blast_cmd
|
403
|
+
@logger.log("NCBI Blast", @cmd)
|
404
|
+
system(@cmd)
|
405
|
+
parse_and_save_results
|
406
|
+
add_hps_groups_to_reports
|
407
|
+
remove_tmp_files
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|