quorum 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +15 -0
  4. data/Gemfile.lock +170 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +318 -0
  7. data/Rakefile +31 -0
  8. data/app/assets/images/quorum/.gitkeep +0 -0
  9. data/app/assets/images/quorum/bg.png +0 -0
  10. data/app/assets/images/quorum/knight_rider.gif +0 -0
  11. data/app/assets/images/quorum/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  12. data/app/assets/images/quorum/ui-bg_flat_75_ffffff_40x100.png +0 -0
  13. data/app/assets/images/quorum/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  14. data/app/assets/images/quorum/ui-bg_glass_65_ffffff_1x400.png +0 -0
  15. data/app/assets/images/quorum/ui-bg_glass_75_dadada_1x400.png +0 -0
  16. data/app/assets/images/quorum/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  17. data/app/assets/images/quorum/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  18. data/app/assets/images/quorum/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
  19. data/app/assets/images/quorum/ui-icons_222222_256x240.png +0 -0
  20. data/app/assets/images/quorum/ui-icons_2e83ff_256x240.png +0 -0
  21. data/app/assets/images/quorum/ui-icons_454545_256x240.png +0 -0
  22. data/app/assets/images/quorum/ui-icons_888888_256x240.png +0 -0
  23. data/app/assets/images/quorum/ui-icons_cd0a0a_256x240.png +0 -0
  24. data/app/assets/javascripts/quorum/application.js +13 -0
  25. data/app/assets/javascripts/quorum/jobs.js +386 -0
  26. data/app/assets/stylesheets/quorum/application.css +224 -0
  27. data/app/assets/stylesheets/quorum/jobs.css +72 -0
  28. data/app/assets/stylesheets/quorum/jquery-ui-1.8.16.custom.css +568 -0
  29. data/app/assets/stylesheets/quorum/tipsy.css +25 -0
  30. data/app/controllers/quorum/application_controller.rb +5 -0
  31. data/app/controllers/quorum/jobs_controller.rb +102 -0
  32. data/app/helpers/quorum/application_helper.rb +4 -0
  33. data/app/models/quorum/blastn_job.rb +111 -0
  34. data/app/models/quorum/blastn_job_report.rb +7 -0
  35. data/app/models/quorum/blastp_job.rb +111 -0
  36. data/app/models/quorum/blastp_job_report.rb +7 -0
  37. data/app/models/quorum/blastx_job.rb +111 -0
  38. data/app/models/quorum/blastx_job_report.rb +7 -0
  39. data/app/models/quorum/job.rb +164 -0
  40. data/app/models/quorum/tblastn_job.rb +111 -0
  41. data/app/models/quorum/tblastn_job_report.rb +7 -0
  42. data/app/views/layouts/quorum/application.html.erb +15 -0
  43. data/app/views/quorum/jobs/_blastn_form.html.erb +71 -0
  44. data/app/views/quorum/jobs/_blastp_form.html.erb +71 -0
  45. data/app/views/quorum/jobs/_blastx_form.html.erb +71 -0
  46. data/app/views/quorum/jobs/_tblastn_form.html.erb +71 -0
  47. data/app/views/quorum/jobs/new.html.erb +45 -0
  48. data/app/views/quorum/jobs/show.html.erb +183 -0
  49. data/app/views/shared/_error_messages.html.erb +10 -0
  50. data/config/locales/en.yml +8 -0
  51. data/config/routes.rb +9 -0
  52. data/db/migrate/20111031204518_create_jobs.rb +12 -0
  53. data/db/migrate/20111031204701_create_blastn_jobs.rb +19 -0
  54. data/db/migrate/20111031204719_create_blastx_jobs.rb +19 -0
  55. data/db/migrate/20111031204733_create_blastp_jobs.rb +19 -0
  56. data/db/migrate/20111031204754_create_tblastn_jobs.rb +19 -0
  57. data/db/migrate/20111031204846_create_blastn_job_reports.rb +34 -0
  58. data/db/migrate/20111031204903_create_blastx_job_reports.rb +34 -0
  59. data/db/migrate/20111031204922_create_blastp_job_reports.rb +34 -0
  60. data/db/migrate/20111031204941_create_tblastn_job_reports.rb +34 -0
  61. data/lib/generators/quorum/install_generator.rb +68 -0
  62. data/lib/generators/quorum/styles_generator.rb +18 -0
  63. data/lib/generators/quorum/views_generator.rb +18 -0
  64. data/lib/generators/templates/README +25 -0
  65. data/lib/generators/templates/blast.rb +412 -0
  66. data/lib/generators/templates/logger.rb +43 -0
  67. data/lib/generators/templates/quorum_initializer.rb +36 -0
  68. data/lib/generators/templates/quorum_settings.yml +157 -0
  69. data/lib/generators/templates/search +141 -0
  70. data/lib/generators/templates/trollop.rb +781 -0
  71. data/lib/quorum/engine.rb +5 -0
  72. data/lib/quorum/helpers.rb +17 -0
  73. data/lib/quorum/sequence.rb +89 -0
  74. data/lib/quorum/version.rb +3 -0
  75. data/lib/quorum.rb +89 -0
  76. data/lib/tasks/blastdb/README +17 -0
  77. data/lib/tasks/blastdb/build_blast_db.rb +222 -0
  78. data/lib/tasks/quorum_resque.rake +3 -0
  79. data/lib/tasks/quorum_tasks.rake +50 -0
  80. data/lib/workers/quorum.rb +45 -0
  81. data/quorum.gemspec +29 -0
  82. data/script/rails +6 -0
  83. data/spec/data/nucl_prot_seqs.txt +36 -0
  84. data/spec/data/nucl_seqs.txt +32 -0
  85. data/spec/data/prot_seqs.txt +4 -0
  86. data/spec/data/seqs.docx +0 -0
  87. data/spec/data/seqs_not_fa.txt +16 -0
  88. data/spec/data/tmp/test.tgz +0 -0
  89. data/spec/dummy/Rakefile +7 -0
  90. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  91. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  92. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  93. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  94. data/spec/dummy/app/mailers/.gitkeep +0 -0
  95. data/spec/dummy/app/models/.gitkeep +0 -0
  96. data/spec/dummy/app/models/blast.rb +2 -0
  97. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  98. data/spec/dummy/config/application.rb +46 -0
  99. data/spec/dummy/config/boot.rb +10 -0
  100. data/spec/dummy/config/environment.rb +20 -0
  101. data/spec/dummy/config/environments/development.rb +30 -0
  102. data/spec/dummy/config/environments/production.rb +60 -0
  103. data/spec/dummy/config/environments/test.rb +42 -0
  104. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  105. data/spec/dummy/config/initializers/inflections.rb +10 -0
  106. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  107. data/spec/dummy/config/initializers/quorum_initializer.rb +36 -0
  108. data/spec/dummy/config/initializers/resque.rb +1 -0
  109. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  110. data/spec/dummy/config/initializers/session_store.rb +8 -0
  111. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  112. data/spec/dummy/config/locales/en.yml +5 -0
  113. data/spec/dummy/config/locales/quorum.en.yml +8 -0
  114. data/spec/dummy/config/quorum_settings.yml +145 -0
  115. data/spec/dummy/config/routes.rb +9 -0
  116. data/spec/dummy/config.ru +4 -0
  117. data/spec/dummy/db/schema.rb +214 -0
  118. data/spec/dummy/lib/assets/.gitkeep +0 -0
  119. data/spec/dummy/log/.gitkeep +0 -0
  120. data/spec/dummy/public/404.html +26 -0
  121. data/spec/dummy/public/422.html +26 -0
  122. data/spec/dummy/public/500.html +26 -0
  123. data/spec/dummy/public/favicon.ico +0 -0
  124. data/spec/dummy/quorum/bin/search +141 -0
  125. data/spec/dummy/quorum/blastdb/test/contigs.fa +2 -0
  126. data/spec/dummy/quorum/blastdb/test/peptides.fa +2 -0
  127. data/spec/dummy/quorum/blastdb/test.nhd +1 -0
  128. data/spec/dummy/quorum/blastdb/test.nhi +0 -0
  129. data/spec/dummy/quorum/blastdb/test.nhr +0 -0
  130. data/spec/dummy/quorum/blastdb/test.nin +0 -0
  131. data/spec/dummy/quorum/blastdb/test.nog +0 -0
  132. data/spec/dummy/quorum/blastdb/test.nsd +1 -0
  133. data/spec/dummy/quorum/blastdb/test.nsi +0 -0
  134. data/spec/dummy/quorum/blastdb/test.nsq +0 -0
  135. data/spec/dummy/quorum/blastdb/test.phd +1 -0
  136. data/spec/dummy/quorum/blastdb/test.phi +0 -0
  137. data/spec/dummy/quorum/blastdb/test.phr +0 -0
  138. data/spec/dummy/quorum/blastdb/test.pin +0 -0
  139. data/spec/dummy/quorum/blastdb/test.pog +0 -0
  140. data/spec/dummy/quorum/blastdb/test.psd +1 -0
  141. data/spec/dummy/quorum/blastdb/test.psi +0 -0
  142. data/spec/dummy/quorum/blastdb/test.psq +0 -0
  143. data/spec/dummy/quorum/lib/logger.rb +43 -0
  144. data/spec/dummy/quorum/lib/search_tools/blast.rb +412 -0
  145. data/spec/dummy/quorum/lib/trollop.rb +781 -0
  146. data/spec/dummy/script/rails +6 -0
  147. data/spec/models/blastn_job_report_spec.rb +13 -0
  148. data/spec/models/blastn_job_spec.rb +103 -0
  149. data/spec/models/blastp_job_report_spec.rb +13 -0
  150. data/spec/models/blastp_job_spec.rb +103 -0
  151. data/spec/models/blastx_job_report_spec.rb +13 -0
  152. data/spec/models/blastx_job_spec.rb +103 -0
  153. data/spec/models/job_spec.rb +40 -0
  154. data/spec/models/tblastn_job_report_spec.rb +13 -0
  155. data/spec/models/tblastn_job_spec.rb +103 -0
  156. data/spec/quorum/quorum_sequence_spec.rb +64 -0
  157. data/spec/quorum_installed_spec.rb +64 -0
  158. data/spec/requests/jobs_spec.rb +138 -0
  159. data/spec/spec_helper.rb +45 -0
  160. data/spec/tasks/blastdb_rake_spec.rb +119 -0
  161. data/spec/templates/blast_spec.rb +8 -0
  162. data/spec/templates/logger_spec.rb +35 -0
  163. data/vendor/assets/javascripts/jquery.tipsy.js +241 -0
  164. data/vendor/assets/javascripts/underscore-min.js +30 -0
  165. metadata +325 -0
@@ -0,0 +1,102 @@
1
+ module Quorum
2
+ class JobsController < ApplicationController
3
+
4
+ respond_to :html, :json
5
+ before_filter :set_blast_dbs, :only => [:new, :create]
6
+
7
+ def index
8
+ redirect_to :action => "new"
9
+ end
10
+
11
+ def new
12
+ @job = Job.new
13
+ @job.build_blastn_job
14
+ @job.build_blastx_job
15
+ @job.build_tblastn_job
16
+ @job.build_blastp_job
17
+ end
18
+
19
+ def create
20
+ if params[:job][:sequence_file]
21
+ file = params[:job][:sequence_file].read
22
+ params[:job].delete(:sequence_file)
23
+ end
24
+
25
+ @job = Job.new(params[:job])
26
+
27
+ if file
28
+ @job.sequence = ""
29
+ @job.sequence << file
30
+ end
31
+
32
+ unless @job.save
33
+ @job.build_blastn_job if @job.blastn_job.nil?
34
+ @job.build_blastx_job if @job.blastx_job.nil?
35
+ @job.build_tblastn_job if @job.tblastn_job.nil?
36
+ @job.build_blastp_job if @job.blastp_job.nil?
37
+ render :action => "new"
38
+ return
39
+ end
40
+ redirect_to job_path(@job.id)
41
+ end
42
+
43
+ def show
44
+ begin
45
+ @jobs = Job.find(params[:id])
46
+ rescue ActiveRecord::RecordNotFound => e
47
+ set_flash_message(:notice, :data_not_found)
48
+ redirect_to :action => "new"
49
+ end
50
+ end
51
+
52
+ #
53
+ # Returns Resque worker results.
54
+ #
55
+ def get_quorum_search_results
56
+ valid = ["blastn", "blastx", "tblastn", "blastp"]
57
+ empty = [{ :results => false }].to_json
58
+
59
+ json = empty
60
+
61
+ if valid.include? params[:algo]
62
+ queued = "#{params[:algo]}_job".to_sym
63
+ report = "#{params[:algo]}_job_reports".to_sym
64
+
65
+ begin
66
+ job = Job.find(params[:id])
67
+ rescue ActiveRecord::RecordNotFound => e
68
+ json = empty
69
+ else
70
+ if job.method(queued).call.present?
71
+ if job.method(report).call.present?
72
+ if params[:query]
73
+ json = job.method(report).call.by_query(params[:query]).default_order
74
+ else
75
+ json = job.method(report).call.default_order
76
+ end
77
+ else
78
+ json = []
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ respond_with json
85
+ end
86
+
87
+ private
88
+
89
+ #
90
+ # Blast Database options for select.
91
+ #
92
+ def set_blast_dbs
93
+ @blast_dbs = {
94
+ :blastn => Quorum.blastn,
95
+ :blastx => Quorum.blastx,
96
+ :tblastn => Quorum.tblastn,
97
+ :blastp => Quorum.blastp
98
+ }
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,4 @@
1
+ module Quorum
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,111 @@
1
+ module Quorum
2
+ class BlastnJob < ActiveRecord::Base
3
+
4
+ before_save :set_optional_params, :set_blast_dbs
5
+
6
+ belongs_to :job
7
+ has_many :blastn_job_reports,
8
+ :dependent => :destroy,
9
+ :foreign_key => :blastn_job_id,
10
+ :primary_key => :job_id
11
+
12
+ attr_accessible :expectation, :max_score, :min_bit_score,
13
+ :filter, :gapped_alignments, :gap_opening_penalty,
14
+ :gap_extension_penalty, :gap_opening_extension, :queue,
15
+ :blast_dbs
16
+
17
+ validates_format_of :expectation,
18
+ :with => /^[+-]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/,
19
+ :message => " - Valid formats (12, 32.05, 43e-123)",
20
+ :allow_blank => true
21
+ validates_numericality_of :max_score,
22
+ :only_integer => true,
23
+ :allow_blank => true
24
+ validates_numericality_of :min_bit_score,
25
+ :only_integer => true,
26
+ :allow_blank => true
27
+ validates_numericality_of :gap_opening_penalty,
28
+ :only_integer => true,
29
+ :allow_blank => true
30
+ validates_numericality_of :gap_extension_penalty,
31
+ :only_integer => true,
32
+ :allow_blank => true
33
+ validates_presence_of :blast_dbs, :if => :queue
34
+ validate :gap_opening_extension_exists
35
+
36
+ #
37
+ # Gapped alignment helper.
38
+ #
39
+ def gapped_alignment?
40
+ self.gapped_alignments
41
+ end
42
+
43
+ #
44
+ # Valid gap opening and extension values.
45
+ #
46
+ def gap_opening_extension_values
47
+ [
48
+ ['--Select--', ''],
49
+ ['32767, 32767', '32767,32767'],
50
+ ['11, 2', '11,2'],
51
+ ['10, 2', '10,2'],
52
+ ['9, 2', '9,2'],
53
+ ['8, 2', '8,2'],
54
+ ['7, 2', '7,2'],
55
+ ['6, 2', '6,2'],
56
+ ['13, 1', '13,1'],
57
+ ['12, 1', '12,1'],
58
+ ['11, 1', '11,1'],
59
+ ['10, 1', '10,1'],
60
+ ['9, 1', '9,1']
61
+ ]
62
+ end
63
+
64
+ #
65
+ # Virtual attribute getter.
66
+ #
67
+ def gap_opening_extension
68
+ [gap_opening_penalty, gap_extension_penalty].join(',')
69
+ end
70
+
71
+ #
72
+ # Virtual attribute setter.
73
+ #
74
+ def gap_opening_extension=(value)
75
+ v = value.split(',')
76
+ self.gap_opening_penalty = v.first
77
+ self.gap_extension_penalty = v.last
78
+ end
79
+
80
+ private
81
+
82
+ def set_blast_dbs
83
+ if self.blast_dbs.present?
84
+ self.blast_dbs = self.blast_dbs.join(';')
85
+ end
86
+ end
87
+
88
+ def set_optional_params
89
+ self.expectation = "5e-10" if self.expectation.blank?
90
+ self.max_score ||= 25
91
+ self.min_bit_score ||= 0
92
+ unless self.gapped_alignments
93
+ self.gap_opening_penalty = 0
94
+ self.gap_extension_penalty = 0
95
+ end
96
+ end
97
+
98
+ #
99
+ # Add error if gapped_alignment? without gap_opening_extension.
100
+ #
101
+ def gap_opening_extension_exists
102
+ if gap_opening_extension.split(',').blank? && gapped_alignment?
103
+ errors.add(
104
+ :gap_opening_extension,
105
+ " - Please select a value."
106
+ )
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,7 @@
1
+ module Quorum
2
+ class BlastnJobReport < ActiveRecord::Base
3
+ belongs_to :blastn_job
4
+ scope :default_order, order("query ASC, bit_score DESC")
5
+ scope :by_query, lambda { |query| where("query = ?", query) }
6
+ end
7
+ end
@@ -0,0 +1,111 @@
1
+ module Quorum
2
+ class BlastpJob < ActiveRecord::Base
3
+
4
+ before_save :set_optional_params, :set_blast_dbs
5
+
6
+ belongs_to :job
7
+ has_many :blastp_job_reports,
8
+ :dependent => :destroy,
9
+ :foreign_key => :blastp_job_id,
10
+ :primary_key => :job_id
11
+
12
+ attr_accessible :expectation, :max_score, :min_bit_score,
13
+ :filter, :gapped_alignments, :gap_opening_penalty,
14
+ :gap_extension_penalty, :gap_opening_extension, :queue,
15
+ :blast_dbs
16
+
17
+ validates_format_of :expectation,
18
+ :with => /^[+-]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/,
19
+ :message => " - Valid formats (12, 32.05, 43e-123)",
20
+ :allow_blank => true
21
+ validates_numericality_of :max_score,
22
+ :only_integer => true,
23
+ :allow_blank => true
24
+ validates_numericality_of :min_bit_score,
25
+ :only_integer => true,
26
+ :allow_blank => true
27
+ validates_numericality_of :gap_opening_penalty,
28
+ :only_integer => true,
29
+ :allow_blank => true
30
+ validates_numericality_of :gap_extension_penalty,
31
+ :only_integer => true,
32
+ :allow_blank => true
33
+ validates_presence_of :blast_dbs, :if => :queue
34
+ validate :gap_opening_extension_exists
35
+
36
+ #
37
+ # Gapped alignment helper.
38
+ #
39
+ def gapped_alignment?
40
+ self.gapped_alignments
41
+ end
42
+
43
+ #
44
+ # Valid gap opening and extension values.
45
+ #
46
+ def gap_opening_extension_values
47
+ [
48
+ ['--Select--', ''],
49
+ ['32767, 32767', '32767,32767'],
50
+ ['11, 2', '11,2'],
51
+ ['10, 2', '10,2'],
52
+ ['9, 2', '9,2'],
53
+ ['8, 2', '8,2'],
54
+ ['7, 2', '7,2'],
55
+ ['6, 2', '6,2'],
56
+ ['13, 1', '13,1'],
57
+ ['12, 1', '12,1'],
58
+ ['11, 1', '11,1'],
59
+ ['10, 1', '10,1'],
60
+ ['9, 1', '9,1']
61
+ ]
62
+ end
63
+
64
+ #
65
+ # Virtual attribute getter.
66
+ #
67
+ def gap_opening_extension
68
+ [gap_opening_penalty, gap_extension_penalty].join(',')
69
+ end
70
+
71
+ #
72
+ # Virtual attribute setter.
73
+ #
74
+ def gap_opening_extension=(value)
75
+ v = value.split(',')
76
+ self.gap_opening_penalty = v.first
77
+ self.gap_extension_penalty = v.last
78
+ end
79
+
80
+ private
81
+
82
+ def set_blast_dbs
83
+ if self.blast_dbs.present?
84
+ self.blast_dbs = self.blast_dbs.join(';')
85
+ end
86
+ end
87
+
88
+ def set_optional_params
89
+ self.expectation = "5e-20" if self.expectation.blank?
90
+ self.max_score ||= 25
91
+ self.min_bit_score ||= 0
92
+ unless self.gapped_alignments
93
+ self.gap_opening_penalty = 0
94
+ self.gap_extension_penalty = 0
95
+ end
96
+ end
97
+
98
+ #
99
+ # Add error if gapped_alignment? without gap_opening_extension.
100
+ #
101
+ def gap_opening_extension_exists
102
+ if gap_opening_extension.split(',').blank? && gapped_alignment?
103
+ errors.add(
104
+ :gap_opening_extension,
105
+ " - Please select a value."
106
+ )
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,7 @@
1
+ module Quorum
2
+ class BlastpJobReport < ActiveRecord::Base
3
+ belongs_to :blastp_job
4
+ scope :default_order, order("query ASC, bit_score DESC")
5
+ scope :by_query, lambda { |query| where("query = ?", query) }
6
+ end
7
+ end
@@ -0,0 +1,111 @@
1
+ module Quorum
2
+ class BlastxJob < ActiveRecord::Base
3
+
4
+ before_save :set_optional_params, :set_blast_dbs
5
+
6
+ belongs_to :job
7
+ has_many :blastx_job_reports,
8
+ :dependent => :destroy,
9
+ :foreign_key => :blastx_job_id,
10
+ :primary_key => :job_id
11
+
12
+ attr_accessible :expectation, :max_score, :min_bit_score,
13
+ :filter, :gapped_alignments, :gap_opening_penalty,
14
+ :gap_extension_penalty, :gap_opening_extension, :queue,
15
+ :blast_dbs
16
+
17
+ validates_format_of :expectation,
18
+ :with => /^[+-]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/,
19
+ :message => " - Valid formats (12, 32.05, 43e-123)",
20
+ :allow_blank => true
21
+ validates_numericality_of :max_score,
22
+ :only_integer => true,
23
+ :allow_blank => true
24
+ validates_numericality_of :min_bit_score,
25
+ :only_integer => true,
26
+ :allow_blank => true
27
+ validates_numericality_of :gap_opening_penalty,
28
+ :only_integer => true,
29
+ :allow_blank => true
30
+ validates_numericality_of :gap_extension_penalty,
31
+ :only_integer => true,
32
+ :allow_blank => true
33
+ validates_presence_of :blast_dbs, :if => :queue
34
+ validate :gap_opening_extension_exists
35
+
36
+ #
37
+ # Gapped alignment helper.
38
+ #
39
+ def gapped_alignment?
40
+ self.gapped_alignments
41
+ end
42
+
43
+ #
44
+ # Valid gap opening and extension values.
45
+ #
46
+ def gap_opening_extension_values
47
+ [
48
+ ['--Select--', ''],
49
+ ['32767, 32767', '32767,32767'],
50
+ ['11, 2', '11,2'],
51
+ ['10, 2', '10,2'],
52
+ ['9, 2', '9,2'],
53
+ ['8, 2', '8,2'],
54
+ ['7, 2', '7,2'],
55
+ ['6, 2', '6,2'],
56
+ ['13, 1', '13,1'],
57
+ ['12, 1', '12,1'],
58
+ ['11, 1', '11,1'],
59
+ ['10, 1', '10,1'],
60
+ ['9, 1', '9,1']
61
+ ]
62
+ end
63
+
64
+ #
65
+ # Virtual attribute getter.
66
+ #
67
+ def gap_opening_extension
68
+ [gap_opening_penalty, gap_extension_penalty].join(',')
69
+ end
70
+
71
+ #
72
+ # Virtual attribute setter.
73
+ #
74
+ def gap_opening_extension=(value)
75
+ v = value.split(',')
76
+ self.gap_opening_penalty = v.first
77
+ self.gap_extension_penalty = v.last
78
+ end
79
+
80
+ private
81
+
82
+ def set_blast_dbs
83
+ if self.blast_dbs.present?
84
+ self.blast_dbs = self.blast_dbs.join(';')
85
+ end
86
+ end
87
+
88
+ def set_optional_params
89
+ self.expectation = "5e-20" if self.expectation.blank?
90
+ self.max_score ||= 25
91
+ self.min_bit_score ||= 0
92
+ unless self.gapped_alignments
93
+ self.gap_opening_penalty = 0
94
+ self.gap_extension_penalty = 0
95
+ end
96
+ end
97
+
98
+ #
99
+ # Add error if gapped_alignment? without gap_opening_extension.
100
+ #
101
+ def gap_opening_extension_exists
102
+ if gap_opening_extension.split(',').blank? && gapped_alignment?
103
+ errors.add(
104
+ :gap_opening_extension,
105
+ " - Please select a value."
106
+ )
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,7 @@
1
+ module Quorum
2
+ class BlastxJobReport < ActiveRecord::Base
3
+ belongs_to :blastx_job
4
+ scope :default_order, order("query ASC, bit_score DESC")
5
+ scope :by_query, lambda { |query| where("query = ?", query) }
6
+ end
7
+ end
@@ -0,0 +1,164 @@
1
+ module Quorum
2
+ class Job < ActiveRecord::Base
3
+
4
+ include Quorum::Sequence
5
+
6
+ after_save :queue_workers
7
+
8
+ has_one :blastn_job, :dependent => :destroy
9
+ has_many :blastn_job_reports, :through => :blastn_job,
10
+ :dependent => :destroy
11
+
12
+ has_one :blastx_job, :dependent => :destroy
13
+ has_many :blastx_job_reports, :through => :blastx_job,
14
+ :dependent => :destroy
15
+
16
+ has_one :tblastn_job, :dependent => :destroy
17
+ has_many :tblastn_job_reports, :through => :tblastn_job,
18
+ :dependent => :destroy
19
+
20
+ has_one :blastp_job, :dependent => :destroy
21
+ has_many :blastp_job_reports, :through => :blastp_job,
22
+ :dependent => :destroy
23
+
24
+ accepts_nested_attributes_for :blastn_job, :blastx_job, :tblastn_job,
25
+ :blastp_job,
26
+ :reject_if => proc { |attributes| attributes['queue'] == '0' }
27
+
28
+ attr_accessible :sequence, :na_sequence, :aa_sequence,
29
+ :blastn_job_attributes, :blastx_job_attributes, :tblastn_job_attributes,
30
+ :blastp_job_attributes
31
+
32
+ validates_associated :blastn_job, :blastx_job, :tblastn_job, :blastp_job
33
+
34
+ validate :filter_input_sequences, :algorithm_selected
35
+
36
+ private
37
+
38
+ #
39
+ # Filter input sequences by type (AA or NA) and place each in it's
40
+ # appropriate attribute.
41
+ #
42
+ def filter_input_sequences
43
+ # Ensure the sequences are in plain text.
44
+ begin
45
+ ActiveSupport::Multibyte::Unicode.u_unpack(self.sequence)
46
+ rescue ActiveSupport::Multibyte::EncodingError => e
47
+ logger.error e.message
48
+ errors.add(
49
+ :sequence,
50
+ "Please enter your sequence(s) in Plain Text as FASTA."
51
+ )
52
+ self.sequence = ""
53
+ return
54
+ end
55
+
56
+ hash = create_hash(self.sequence)
57
+ tmp = File.join(::Rails.root.to_s, 'tmp')
58
+
59
+ # Ensure the sequences are FASTA via #write_input_sequence_to_file.
60
+ begin
61
+ write_input_sequence_to_file(tmp, hash, self.sequence)
62
+ rescue Exception => e
63
+ errors.add(:sequence, e.message)
64
+ return
65
+ else
66
+ fasta = File.read(File.join(tmp, hash + ".fa"))
67
+ ensure
68
+ File.delete(File.join(tmp, hash + ".fa"))
69
+ File.delete(File.join(tmp, hash + ".seq"))
70
+ end
71
+
72
+ self.na_sequence = ""
73
+ self.aa_sequence = ""
74
+
75
+ # Split the sequences on >, check the type (AA or NA) and separate.
76
+ seqs = fasta.split('>')
77
+ seqs.delete_if { |s| s.empty? }
78
+ seqs.each do |s|
79
+ type = discover_input_sequence_type(s)
80
+ if type == "nucleic_acid"
81
+ self.na_sequence << ">" << s
82
+ end
83
+ if type == "amino_acid"
84
+ self.aa_sequence << ">" << s
85
+ end
86
+ end
87
+
88
+ self.na_sequence = nil if self.na_sequence.empty?
89
+ self.aa_sequence = nil if self.aa_sequence.empty?
90
+ end
91
+
92
+ #
93
+ # Make sure an algorithm is selected.
94
+ #
95
+ def algorithm_selected
96
+ in_queue = false
97
+ if (self.blastn_job && self.blastn_job.queue) ||
98
+ (self.blastx_job && self.blastx_job.queue) ||
99
+ (self.tblastn_job && self.tblastn_job.queue) ||
100
+ (self.blastp_job && self.blastp_job.queue)
101
+ in_queue = true
102
+ end
103
+ unless in_queue
104
+ errors.add(
105
+ :algorithm,
106
+ " - Please select at least one algorithm to continue."
107
+ )
108
+ end
109
+ end
110
+
111
+ #
112
+ # Queue Resque workers.
113
+ #
114
+ def queue_workers
115
+ jobs = []
116
+ if self.blastn_job && self.blastn_job.queue
117
+ jobs << create_system_command("blastn")
118
+ end
119
+ if self.blastx_job && self.blastx_job.queue
120
+ jobs << create_system_command("blastx")
121
+ end
122
+ if self.tblastn_job && self.tblastn_job.queue
123
+ jobs << create_system_command("tblastn")
124
+ end
125
+ if self.blastp_job && self.blastp_job.queue
126
+ jobs << create_system_command("blastp")
127
+ end
128
+
129
+ unless jobs.blank?
130
+ jobs.each do |j|
131
+ Resque.enqueue(
132
+ Workers::System, j, Quorum.blast_remote,
133
+ Quorum.blast_ssh_host, Quorum.blast_ssh_user,
134
+ Quorum.blast_ssh_options
135
+ )
136
+ end
137
+ end
138
+ end
139
+
140
+ #
141
+ # Create system commands based on config/quorum_settings.yml
142
+ #
143
+ def create_system_command(algorithm)
144
+ # System command
145
+ cmd = ""
146
+
147
+ if Quorum::BLAST_ALGORITHMS.include?(algorithm)
148
+ cmd << "#{Quorum.blast_script} -l #{Quorum.blast_log_dir} " <<
149
+ "-m #{Quorum.blast_tmp_dir} -b #{Quorum.blast_db} " <<
150
+ "-t #{Quorum.blast_threads} "
151
+ else
152
+ return cmd
153
+ end
154
+
155
+ cmd << "-s #{algorithm} -i #{self.id} " <<
156
+ "-d #{ActiveRecord::Base.configurations[::Rails.env.to_s]['database']} " <<
157
+ "-a #{ActiveRecord::Base.configurations[::Rails.env.to_s]['adapter']} " <<
158
+ "-k #{ActiveRecord::Base.configurations[::Rails.env.to_s]['host']} " <<
159
+ "-u #{ActiveRecord::Base.configurations[::Rails.env.to_s]['username']} " <<
160
+ "-p #{ActiveRecord::Base.configurations[::Rails.env.to_s]['password']} "
161
+ end
162
+
163
+ end
164
+ end