quorum 0.1.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.
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