miga-base 0.7.3.1 → 0.7.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e3f943800139b48778d227b3f0680bd71cac91774037f9f9e115842ccb3e6f4
4
- data.tar.gz: 351042f7e77d3b2a3189a27fc37ead6c4fdb02ad519ba72a760d8e75a50dddf3
3
+ metadata.gz: 917085ea3480e143d61e0ce468cf041cd6ad4f7b45b4231c7239037a44bd1879
4
+ data.tar.gz: 9b6751862e49aee3980133dc16d85d51d973111ad5db9eb15dcbb369972e548d
5
5
  SHA512:
6
- metadata.gz: 95f0728ad6f0d4359c32ed37deb9b215e6ecbd15fd5807796a8927eadb5ebfc1466d88e94afec179b33df9009d53e2f109166c5db5bf82424d6c31c6289cf780
7
- data.tar.gz: 75a5c9f95150c0177f1cf29a2bac58547bb51e60f75fe1d3c42acc3a3945aee161d51e1af479187459312b39c9164a6955d28232cbeb923cb8dbe5b748b590d8
6
+ metadata.gz: 3bd3c871edb8ffe3cb71e697d56cd9108501073db882b9ea61c58a243bfee6c31040a2197211f4c97b963dccd629f0639b4e3894b8a5173db77c3a3ee4088065
7
+ data.tar.gz: c14f8d8b194e8691a194a5c99ebb06720c079808ce41a687c7d9106cb1e49d8baaf0e52aee3bf55bd750534ea85121fa9dab820419b42fb1b2927e71fe72a467
@@ -0,0 +1,79 @@
1
+
2
+ require 'miga/cli/action'
3
+ require 'sqlite3'
4
+
5
+ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
6
+ end
7
+
8
+ module MiGA::Cli::Action::Doctor::Base
9
+ ##
10
+ # Check the database in +db_file+ maintains integrity for the
11
+ # tables saving +metric+ (:ani or :aai)
12
+ def check_sqlite3_database(db_file, metric)
13
+ SQLite3::Database.new(db_file) do |conn|
14
+ conn.execute("select count(*) from #{metric}").first
15
+ end
16
+ rescue SQLite3::SQLException
17
+ yield
18
+ end
19
+
20
+ ##
21
+ # Scans the all-vs-all matrix registered in +res+ (MiGA::Result) in search of
22
+ # pairs where one or both datasets are missing or inactive in the project +p+
23
+ # (MiGA::Project), and report progress through +cli+ (MiGA::Cli).
24
+ # Returns an Array with two arrays: the first a list of dataset names that are
25
+ # no longer registered in the project or are currently inactive, and the
26
+ # second a list of dataset names that have registered pairs with the first
27
+ # list, and therefore the databases need to be cleaned.
28
+ # This is a subtask of +check_dist+
29
+ def check_dist_eval(cli, p, res)
30
+ notok = {}
31
+ fix = {}
32
+ Zlib::GzipReader.open(res.file_path(:matrix)) do |fh|
33
+ lineno = 0
34
+ fh.each_line do |ln|
35
+ next if (lineno += 1) == 1
36
+ r = ln.split("\t")
37
+ next unless [1, 2].map { |i| p.dataset(r[i]).nil? }.any?
38
+ [1, 2].each do |i|
39
+ if p.dataset(r[i]).nil? || !p.dataset(r[i]).active?
40
+ notok[r[i]] = true
41
+ else
42
+ fix[r[i]] = true
43
+ end
44
+ end
45
+ end
46
+ end
47
+ [notok.keys, fix.keys]
48
+ end
49
+
50
+ ##
51
+ # Cleanup distance databases for datasets names in +fix+ (Array: String)
52
+ # from project +p+ (MiGA::Project), and report through +cli+ (MiGA::Cli).
53
+ # This is a subtask of +check_dist+
54
+ def check_dist_fix(cli, p, fix)
55
+ return if fix.empty?
56
+ cli.say("- Fixing #{fix.size} datasets")
57
+ fix.each do |d_n|
58
+ cli.say " > Fixing #{d_n}."
59
+ p.dataset(d_n).cleanup_distances!
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Recompute +res+ (MiGA::Result) if +notok+ (Array: String) has any dataset
65
+ # names registered, and report through +cli+ (MiGA::Cli).
66
+ # This is a subtask of +check_dist+
67
+ def check_dist_recompute(cli, res, notok)
68
+ return if notok.empty?
69
+ cli.say '- Unregistered datasets detected: '
70
+ if notok.size <= 5
71
+ notok.each { |i| cli.say " > #{i}" }
72
+ else
73
+ cli.say " > #{notok.size}, including #{notok.first}"
74
+ end
75
+ cli.say '- Removing tables, recompute'
76
+ res.remove!
77
+ end
78
+ end
79
+
@@ -1,15 +1,15 @@
1
1
  # @package MiGA
2
2
  # @license Artistic-2.0
3
3
 
4
- require 'miga/cli/action'
5
- require 'sqlite3'
4
+ require 'miga/cli/action/doctor/base'
6
5
 
7
6
  class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
7
+ include MiGA::Cli::Action::Doctor::Base
8
8
 
9
9
  def parse_cli
10
- @@OPERATIONS.keys.each { |i| cli.defaults = { i => true } }
10
+ cli.defaults = Hash[@@OPERATIONS.keys.map { |i| [i, true] }]
11
11
  cli.parse do |opt|
12
- operation_n = Hash[@@OPERATIONS.map { |k,v| [v[0], k] }]
12
+ operation_n = Hash[@@OPERATIONS.map { |k, v| [v[0], k] }]
13
13
  cli.opt_object(opt, [:project])
14
14
  opt.on(
15
15
  '--ignore TASK1,TASK2', Array,
@@ -21,20 +21,12 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
21
21
  'Perform only the specified task (see --ignore)'
22
22
  ) do |v|
23
23
  op_k = @@OPERATIONS.find { |_, i| i[0] == v.downcase }.first
24
- @@OPERATIONS.keys.each { |i| cli[i] = false }
24
+ @@OPERATIONS.each_key { |i| cli[i] = false }
25
25
  cli[op_k] = true
26
26
  end
27
27
  end
28
28
  end
29
29
 
30
- def check_sqlite3_database(db_file, metric)
31
- SQLite3::Database.new(db_file) do |conn|
32
- conn.execute("select count(*) from #{metric}").first
33
- end
34
- rescue SQLite3::SQLException
35
- yield
36
- end
37
-
38
30
  def perform
39
31
  p = cli.load_project
40
32
  @@OPERATIONS.keys.each do |k|
@@ -43,7 +35,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
43
35
  end
44
36
 
45
37
  @@OPERATIONS = {
46
- db: ['databases', 'Check database files integrity'],
38
+ status: ['status', 'Update metadata status of all datasets'],
39
+ db: ['databases', 'Check integrity of database files'],
47
40
  dist: ['distances', 'Check distance summary tables'],
48
41
  files: ['files', 'Check for outdated files'],
49
42
  cds: ['cds', 'Check for gzipped genes and proteins'],
@@ -52,34 +45,52 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
52
45
  start: ['start', 'Check for lingering .start files'],
53
46
  tax: ['taxonomy', 'Check for taxonomy consistency (not yet implemented)']
54
47
  }
48
+
55
49
  class << self
50
+ ##
51
+ # All supported operations
56
52
  def OPERATIONS
57
53
  @@OPERATIONS
58
54
  end
59
55
  end
60
56
 
57
+ ##
58
+ # Perform status operation with MiGA::Cli +cli+
59
+ def check_status(cli)
60
+ cli.say 'Updating metadata status'
61
+ cli.load_project.each_dataset { |d| d.recalculate_status }
62
+ end
63
+
64
+ ##
65
+ # Perform databases operation with MiGA::Cli +cli+
61
66
  def check_db(cli)
62
- cli.say 'Checking databases integrity'
67
+ cli.say 'Checking integrity of databases'
63
68
  cli.load_project.each_dataset do |d|
64
- [:distances, :taxonomy].each do |r_key|
69
+ %i[distances taxonomy].each do |r_key|
65
70
  r = d.result(r_key) or next
66
- {haai_db: :aai, aai_db: :aai, ani_db: :ani}.each do |db_key, metric|
71
+ { haai_db: :aai, aai_db: :aai, ani_db: :ani }.each do |db_key, metric|
67
72
  db_file = r.file_path(db_key) or next
68
73
  check_sqlite3_database(db_file, metric) do
69
- cli.say(
70
- " > Removing #{db_key} #{r_key} table for #{d.name}")
74
+ cli.say(" > Removing #{db_key} #{r_key} table for #{d.name}")
71
75
  [db_file, r.path(:done), r.path].each do |f|
72
76
  File.unlink(f) if File.exist? f
73
- end # each |f|
74
- end # check_sqlite3_database
75
- end # each |db_key, metric|
76
- end # each |r_key|
77
- end # each |d|
77
+ end
78
+ # /each |f|
79
+ end
80
+ # /check_sqlite3_database
81
+ end
82
+ # /each |db_key, metric|
83
+ end
84
+ # /each |r_key|
85
+ end
86
+ # /each |d|
78
87
  end
79
88
 
89
+ ##
90
+ # Perform distances operation with MiGA::Cli +cli+
80
91
  def check_dist(cli)
81
92
  p = cli.load_project
82
- [:ani, :aai].each do |dist|
93
+ %i[ani aai].each do |dist|
83
94
  res = p.result("#{dist}_distances")
84
95
  next if res.nil?
85
96
  cli.say "Checking #{dist} table for consistent datasets"
@@ -89,6 +100,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
89
100
  end
90
101
  end
91
102
 
103
+ ##
104
+ # Perform files operation with MiGA::Cli +cli+
92
105
  def check_files(cli)
93
106
  cli.say 'Looking for outdated files in results'
94
107
  p = cli.load_project
@@ -110,12 +123,14 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
110
123
  end
111
124
  end
112
125
 
126
+ ##
127
+ # Perform cds operation with MiGA::Cli +cli+
113
128
  def check_cds(cli)
114
129
  cli.say 'Looking for unzipped genes or proteins'
115
130
  cli.load_project.each_dataset do |d|
116
131
  res = d.result(:cds) or next
117
132
  changed = false
118
- [:genes, :proteins, :gff3, :gff2, :tab].each do |f|
133
+ %i[genes proteins gff3 gff2 tab].each do |f|
119
134
  file = res.file_path(f) or next
120
135
  if file !~ /\.gz/
121
136
  cli.say " > Gzipping #{d.name} #{f}"
@@ -131,6 +146,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
131
146
  end
132
147
  end
133
148
 
149
+ ##
150
+ # Perform essential-genes operation with MiGA::Cli +cli+
134
151
  def check_ess(cli)
135
152
  cli.say 'Looking for unarchived essential genes'
136
153
  cli.load_project.each_dataset do |d|
@@ -150,6 +167,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
150
167
  end
151
168
  end
152
169
 
170
+ ##
171
+ # Perform mytaxa-scan operation with MiGA::Cli +cli+
153
172
  def check_mts(cli)
154
173
  cli.say 'Looking for unarchived MyTaxa Scan runs'
155
174
  cli.load_project.each_dataset do |d|
@@ -166,8 +185,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
166
185
  end
167
186
  fix = true
168
187
  end
169
- %w[blast mytaxain wintax gene_ids region_ids].each do |ext|
170
- file = res.file_path(ext.to_sym)
188
+ %i[blast mytaxain wintax gene_ids region_ids].each do |ext|
189
+ file = res.file_path(ext)
171
190
  unless file.nil?
172
191
  FileUtils.rm(file) if File.exist? file
173
192
  fix = true
@@ -180,6 +199,8 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
180
199
  end
181
200
  end
182
201
 
202
+ ##
203
+ # Perform start operation with MiGA::Cli +cli+
183
204
  def check_start(cli)
184
205
  cli.say 'Looking for legacy .start files lingering'
185
206
  cli.load_project.each_dataset do |d|
@@ -192,52 +213,12 @@ class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
192
213
  end
193
214
  end
194
215
 
216
+ ##
217
+ # Perform taxonomy operation with MiGA::Cli +cli+
195
218
  def check_tax(cli)
196
- #cli.say 'o Checking for taxonomy/distances consistency'
219
+ # cli.say 'o Checking for taxonomy/distances consistency'
197
220
  # TODO: Find 95%ANI clusters with entries from different species
198
- end
199
-
200
- private
201
-
202
- def check_dist_eval(cli, p, res)
203
- notok = {}
204
- fix = {}
205
- Zlib::GzipReader.open(res.file_path(:matrix)) do |fh|
206
- lineno = 0
207
- fh.each_line do |ln|
208
- next if (lineno += 1) == 1
209
- r = ln.split("\t")
210
- next unless [1, 2].map { |i| p.dataset(r[i]).nil? }.any?
211
- [1, 2].each do |i|
212
- if p.dataset(r[i]).nil?
213
- notok[r[i]] = true
214
- else
215
- fix[r[i]] = true
216
- end
217
- end
218
- end
219
- end
220
- [notok, fix]
221
- end
222
-
223
- def check_dist_fix(cli, p, fix)
224
- return if fix.empty?
225
- cli.say("- Fixing #{fix.size} datasets")
226
- fix.keys.each do |d_n|
227
- cli.say " > Fixing #{d_n}."
228
- p.dataset(d_n).cleanup_distances!
229
- end
230
- end
231
-
232
- def check_dist_recompute(cli, p, notok)
233
- return if notok.empty?
234
- cli.say '- Unregistered datasets detected: '
235
- if notok.size <= 5
236
- notok.keys.each { |i| cli.say " > #{i}" }
237
- else
238
- cli.say " > #{notok.size}, including #{notok.keys.first}"
239
- end
240
- cli.say '- Removing tables, recompute'
241
- res.remove!
221
+ # TODO: Find different 95%ANI clusters with genomes from the same species
222
+ # TODO: Find AAI values too high or too low for each LCA rank
242
223
  end
243
224
  end
@@ -12,12 +12,25 @@ class MiGA::Cli::Action::Edit < MiGA::Cli::Action
12
12
  '-m', '--metadata STRING',
13
13
  'Metadata as key-value pairs separated by = and delimited by comma',
14
14
  'Values are saved as strings except for booleans (true / false) or nil'
15
- ){ |v| cli[:metadata] = v }
15
+ ) { |v| cli[:metadata] = v }
16
+ opt.on(
17
+ '--activate',
18
+ 'Activate dataset; requires -D'
19
+ ) { |v| cli[:activate] = v }
20
+ opt.on(
21
+ '--inactivate',
22
+ 'Inactivate dataset; requires -D'
23
+ ) { |v| cli[:activate] = !v }
16
24
  end
17
25
  end
18
26
 
19
27
  def perform
20
28
  obj = cli.load_project_or_dataset
29
+ unless cli[:activate].nil?
30
+ cli.ensure_par({ dataset: '-D' },
31
+ '%<name>s is mandatory with --[in-]activate: please provide %<flag>s')
32
+ cli[:activate] ? obj.activate! : obj.inactivate!
33
+ end
21
34
  cli.add_metadata(obj)
22
35
  obj.save
23
36
  end
@@ -14,19 +14,21 @@ module MiGA::Daemon::Base
14
14
  k = k.to_sym
15
15
  unless v.nil?
16
16
  case k
17
- when :latency, :maxjobs, :ppn, :format_version
17
+ when :latency, :maxjobs, :ppn, :format_version, :verbosity
18
18
  v = v.to_i
19
+ if !force && v == 0 && k != :verbosity
20
+ raise "Daemon's #{k} cannot be set to zero"
21
+ end
19
22
  when :shutdown_when_done
20
23
  v = !!v
21
24
  when :nodelist
22
25
  if v =~ /^\$/
23
- vv = ENV[v.sub('$','')] or raise "Unset environment variable: #{v}"
26
+ vv = ENV[v.sub('$', '')] or raise "Unset environment variable: #{v}"
24
27
  v = vv
25
28
  end
26
29
  say "Reading node list: #{v}"
27
30
  v = File.readlines(v).map(&:chomp)
28
31
  end
29
- raise "Daemon's #{k} cannot be set to zero." if !force and v == 0
30
32
  @runopts[k] = v
31
33
  end
32
34
  @runopts[k]
@@ -34,24 +36,43 @@ module MiGA::Daemon::Base
34
36
 
35
37
  ##
36
38
  # Returns Integer indicating the number of seconds to sleep between checks
37
- def latency() runopts(:latency); end
39
+ def latency
40
+ runopts(:latency)
41
+ end
38
42
 
39
43
  ##
40
44
  # Returns Integer indicating the maximum number of concurrent jobs to run
41
- def maxjobs() runopts(:maxjobs); end
45
+ def maxjobs
46
+ runopts(:maxjobs)
47
+ end
42
48
 
43
49
  ##
44
50
  # Returns the path to the list of execution hostnames
45
- def nodelist() runopts(:nodelist); end
51
+ def nodelist
52
+ runopts(:nodelist)
53
+ end
46
54
 
47
55
  ##
48
56
  # Returns Integer indicating the number of CPUs per job
49
- def ppn() runopts(:ppn); end
57
+ def ppn
58
+ runopts(:ppn)
59
+ end
50
60
 
51
61
  ##
52
62
  # Returns Boolean indicating if the daemon should shutdown when processing is
53
63
  # complete
54
- def shutdown_when_done?() !!runopts(:shutdown_when_done); end
64
+ def shutdown_when_done?
65
+ !!runopts(:shutdown_when_done)
66
+ end
55
67
 
68
+ ##
69
+ # Returns the level of verbosity for the daemon as an Integer, or 1 if unset.
70
+ # Verbosity levels are:
71
+ # 0: No output
72
+ # 1: General daemon and job information
73
+ # 2: Same, and indicate when each task is performed (even if nothing happens)
74
+ # 3: Same, and indicate when each loop begins and ends
75
+ def verbosity
76
+ runopts(:verbosity) || 1
77
+ end
56
78
  end
57
-
data/lib/miga/daemon.rb CHANGED
@@ -45,8 +45,9 @@ class MiGA::Daemon < MiGA::MiGA
45
45
  @project = project
46
46
  @runopts = {}
47
47
  json ||= File.join(project.path, 'daemon/daemon.json')
48
+ default_json = File.expand_path('.miga_daemon.json', ENV['MIGA_HOME'])
48
49
  MiGA::Json.parse(
49
- json, default: File.expand_path('.miga_daemon.json', ENV['MIGA_HOME'])
50
+ json, default: File.exist?(default_json) ? default_json : nil
50
51
  ).each { |k,v| runopts(k, v) }
51
52
  update_format_0
52
53
  @jobs_to_run = []
@@ -77,29 +78,54 @@ class MiGA::Daemon < MiGA::MiGA
77
78
  end
78
79
 
79
80
  ##
80
- # Run one loop step. Returns a Boolean indicating if the loop should continue.
81
+ # Run one loop step. Returns a Boolean indicating if the loop should continue
81
82
  def daemon_loop
82
- project.load
83
+ l_say(3, 'Daemon loop start')
84
+ reload_project
83
85
  check_datasets
84
86
  check_project
85
- if shutdown_when_done? and jobs_running.size + jobs_to_run.size == 0
86
- say 'Nothing else to do, shutting down.'
87
+ if shutdown_when_done? && jobs_running.size + jobs_to_run.size == 0
88
+ say 'Nothing else to do, shutting down'
87
89
  return false
88
90
  end
89
91
  flush!
90
- if loop_i >= 12
91
- say 'Probing running jobs'
92
- @loop_i = 0
92
+ if loop_i % 12 == 0
93
93
  purge!
94
+ recalculate_status!
94
95
  end
95
- report_status
96
+ save_status
96
97
  sleep(latency)
98
+ l_say(3, 'Daemon loop end')
97
99
  true
98
100
  end
99
101
 
102
+ def recalculate_status!
103
+ project.each_dataset(&:recalculate_status)
104
+ end
105
+
106
+ ##
107
+ # Send +msg+ to +say+ as long as +level+ is at most +verbosity+
108
+ def l_say(level, *msg)
109
+ say(*msg) if verbosity >= level
110
+ end
111
+
112
+ ##
113
+ # Same as +l_say+ with +level = 1+
114
+ def say(*msg)
115
+ super(*msg) if verbosity >= 1
116
+ end
117
+
118
+ ##
119
+ # Reload the project's metadata
120
+ def reload_project
121
+ l_say(2, 'Reloading project')
122
+ project.load
123
+ end
124
+
100
125
  ##
101
126
  # Report status in a JSON file.
102
- def report_status
127
+ def save_status
128
+ l_say(2, 'Saving current status')
103
129
  MiGA::Json.generate(
104
130
  { jobs_running: @jobs_running, jobs_to_run: @jobs_to_run },
105
131
  File.join(daemon_home, 'status.json')
@@ -134,7 +160,9 @@ class MiGA::Daemon < MiGA::MiGA
134
160
  ##
135
161
  # Traverse datasets
136
162
  def check_datasets
137
- project.each_dataset do |n, ds|
163
+ l_say(2, 'Checking datasets')
164
+ project.each_dataset do |ds|
165
+ next unless ds.status == :incomplete
138
166
  to_run = ds.next_preprocessing(false)
139
167
  queue_job(:d, ds) unless to_run.nil?
140
168
  end
@@ -144,6 +172,7 @@ class MiGA::Daemon < MiGA::MiGA
144
172
  # Check if all reference datasets are pre-processed. If yes, check the
145
173
  # project-level tasks
146
174
  def check_project
175
+ l_say(2, 'Checking project')
147
176
  return if project.dataset_names.empty?
148
177
  return unless project.done_preprocessing?(false)
149
178
  to_run = project.next_task(nil, false)
@@ -199,6 +228,7 @@ class MiGA::Daemon < MiGA::MiGA
199
228
  # possible respecting #maxjobs or #nodelist (if set).
200
229
  def flush!
201
230
  # Check for finished jobs
231
+ l_say(2, 'Checking for finished jobs')
202
232
  @jobs_running.select! do |job|
203
233
  ongoing = case job[:job].to_s
204
234
  when 'd'
@@ -211,8 +241,10 @@ class MiGA::Daemon < MiGA::MiGA
211
241
  say "Completed pid:#{job[:pid]} for #{job[:task_name]}" unless ongoing
212
242
  ongoing
213
243
  end
244
+
214
245
  # Avoid single datasets hogging resources
215
246
  @jobs_to_run.rotate! rand(jobs_to_run.size)
247
+
216
248
  # Launch as many +jobs_to_run+ as possible
217
249
  while hostk = next_host
218
250
  break if jobs_to_run.empty?
@@ -233,6 +265,7 @@ class MiGA::Daemon < MiGA::MiGA
233
265
  ##
234
266
  # Remove dead jobs.
235
267
  def purge!
268
+ say 'Probing running jobs'
236
269
  @jobs_running.select! do |job|
237
270
  `#{runopts(:alive).miga_variables(pid: job[:pid])}`.chomp.to_i == 1
238
271
  end
@@ -4,7 +4,7 @@ module MiGA::Dataset::Status
4
4
  ##
5
5
  # Returns the status of the dataset. If the status is not yet defined,
6
6
  # it recalculates it and, if +save+ is true, saves it in metadata.
7
- # Return values are:
7
+ # Return symbols are:
8
8
  # - +:inactive+ The dataset is currently inactive
9
9
  # - +:incomplete+ The dataset is not yet fully processed
10
10
  # - +:complete+ The dataset is fully processed
@@ -14,12 +14,13 @@ module MiGA::Dataset::Status
14
14
  end
15
15
 
16
16
  ##
17
- # Identify the current status instead of relying on metadata, and save
18
- # it if +save+ is true. Return codes are the same as +status+.
17
+ # Identify the current status and save it if +save+ and the status changed.
18
+ # Return symbols are the same as +status+.
19
19
  def recalculate_status(save = true)
20
+ old_status = metadata[:status]
20
21
  metadata[:status] =
21
- !active? ? :inactive : done_preprocessing? ? :complete : :incomplete
22
- self.save if save
22
+ !active? ? 'inactive' : done_preprocessing? ? 'complete' : 'incomplete'
23
+ self.save if save && (old_status.nil? || old_status != metadata[:status])
23
24
  metadata[:status].to_sym
24
25
  end
25
26
  end
@@ -35,16 +35,12 @@ module MiGA::Project::Dataset
35
35
  end
36
36
 
37
37
  ##
38
- # Iterate through datasets, with one or two variables passed to +blk+.
39
- # If one, the dataset MiGA::Dataset object is passed. If two, the name and
40
- # the dataset object are passed.
38
+ # Iterate through datasets (MiGA::Dataset)
41
39
  def each_dataset(&blk)
42
- metadata[:datasets].each do |name|
43
- if blk.arity == 1
44
- blk.call(dataset(name))
45
- else
46
- blk.call(name, dataset(name))
47
- end
40
+ if block_given?
41
+ metadata[:datasets].each { |name| blk.call(dataset(name)) }
42
+ else
43
+ to_enum(:each_dataset)
48
44
  end
49
45
  end
50
46
 
@@ -140,9 +136,7 @@ module MiGA::Project::Dataset
140
136
  # - 2: To do.
141
137
  def profile_datasets_advance
142
138
  advance = []
143
- self.each_dataset_profile_advance do |ds_adv|
144
- advance << ds_adv
145
- end
139
+ each_dataset_profile_advance { |adv| advance << adv }
146
140
  advance
147
141
  end
148
142
 
@@ -154,4 +148,3 @@ module MiGA::Project::Dataset
154
148
  end
155
149
 
156
150
  end
157
-
data/lib/miga/version.rb CHANGED
@@ -10,7 +10,7 @@ module MiGA
10
10
  # - Float representing the major.minor version.
11
11
  # - Integer representing gem releases of the current version.
12
12
  # - Integer representing minor changes that require new version number.
13
- VERSION = [0.7, 3, 1]
13
+ VERSION = [0.7, 4, 0]
14
14
 
15
15
  ##
16
16
  # Nickname for the current major.minor version.
@@ -18,7 +18,7 @@ module MiGA
18
18
 
19
19
  ##
20
20
  # Date of the current gem release.
21
- VERSION_DATE = Date.new(2020, 4, 23)
21
+ VERSION_DATE = Date.new(2020, 4, 28)
22
22
 
23
23
  ##
24
24
  # Reference of MiGA.
data/test/daemon_test.rb CHANGED
@@ -88,7 +88,7 @@ class DaemonTest < Test::Unit::TestCase
88
88
  assert_equal(11, d.loop_i)
89
89
  out = capture_stderr { d.in_loop }.string
90
90
  assert_match(/Probing running jobs/, out)
91
- assert_equal(0, d.loop_i)
91
+ assert_equal(12, d.loop_i)
92
92
  end
93
93
 
94
94
  def test_start
@@ -109,6 +109,7 @@ class DaemonTest < Test::Unit::TestCase
109
109
  assert_match(/Sending termination message/, out)
110
110
  assert_path_not_exist(d.pid_file)
111
111
  assert_path_exist(d.output_file)
112
+ assert_equal(1, d.verbosity)
112
113
  l = File.readlines(d.output_file)
113
114
  {
114
115
  0 => /-{20}\n/,
@@ -312,6 +313,26 @@ class DaemonTest < Test::Unit::TestCase
312
313
  assert_equal(1, d1.jobs_to_run.size)
313
314
  end
314
315
 
316
+ def test_verbosity
317
+ d1 = $d1
318
+ d1.runopts(:verbosity, 0)
319
+ out = capture_stderr { d1.in_loop }.string
320
+ assert_empty(out)
321
+
322
+ d1.runopts(:verbosity, 1)
323
+ helper_datasets_with_results.first.inactivate!
324
+ out = capture_stderr { d1.check_project }
325
+ assert_match(/Queueing miga-project:p/, out.string)
326
+
327
+ d1.runopts(:verbosity, 2)
328
+ out = capture_stderr { d1.in_loop }.string
329
+ assert_match(/Reloading project/, out)
330
+
331
+ d1.runopts(:verbosity, 3)
332
+ out = capture_stderr { d1.in_loop }.string
333
+ assert_match(/Daemon loop start/, out)
334
+ end
335
+
315
336
  def helper_daemon_launch_job
316
337
  omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
317
338
  d1 = $d1
@@ -324,5 +345,4 @@ class DaemonTest < Test::Unit::TestCase
324
345
  assert_equal(0, d1.jobs_to_run.size, 'There should be nothing running')
325
346
  assert_equal(1, d1.jobs_running.size, 'There should be one job running')
326
347
  end
327
-
328
348
  end
data/test/project_test.rb CHANGED
@@ -58,7 +58,6 @@ class ProjectTest < Test::Unit::TestCase
58
58
  assert_equal([d], p.datasets)
59
59
  assert_equal(['d1'], p.dataset_names)
60
60
  p.each_dataset { |ds| assert_equal(d, ds) }
61
- p.each_dataset { |n, ds| assert_equal(n, ds.name) }
62
61
  dr = p.unlink_dataset('d1')
63
62
  assert_equal(d, dr)
64
63
  assert_equal([], p.datasets)
@@ -40,12 +40,12 @@ class TaxDistTest < Test::Unit::TestCase
40
40
  def test_aai_taxtest
41
41
  distant_intax = MiGA::TaxDist.aai_taxtest(35.0, :intax, engine: :diamond)
42
42
  assert_equal(:root, distant_intax[:most_likely][0])
43
- assert_nil(distant_intax[:probably])
43
+ assert_equal(:d, distant_intax[:probably][0])
44
44
  assert_nil(distant_intax[:possibly_even])
45
45
 
46
46
  distant_intax = MiGA::TaxDist.aai_taxtest(35.0, :intax, engine: :blast)
47
47
  assert_equal(:root, distant_intax[:most_likely][0])
48
- assert_nil(distant_intax[:probably])
48
+ assert_equal(:d, distant_intax[:probably][0])
49
49
  assert_nil(distant_intax[:possibly_even])
50
50
 
51
51
  close_intax = MiGA::TaxDist.aai_taxtest(99.0, :intax, engine: :diamond)
@@ -16,14 +16,13 @@ def searchable(db, d, k, v)
16
16
  d.name, k.to_s, " #{v.to_s.downcase.gsub(/[^A-Za-z0-9\-]+/, ' ')} "
17
17
  end
18
18
 
19
- p.each_dataset do |name, d|
19
+ p.each_dataset do |d|
20
20
  next unless d.is_ref?
21
21
  next unless d.is_active?
22
22
  searchable(db, d, :name, d.name)
23
23
  d.metadata.each do |k, v|
24
24
  next if [:created, :updated].include? k
25
- v = v.sorted_ranks.map{ |r| r[1] }.join(" ") if k==:tax
25
+ v = v.sorted_ranks.map{ |r| r[1] }.join(' ') if k == :tax
26
26
  searchable(db, d, k, v)
27
27
  end
28
28
  end
29
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miga-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3.1
4
+ version: 0.7.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis M. Rodriguez-R
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-23 00:00:00.000000000 Z
11
+ date: 2020-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: daemons
@@ -124,6 +124,7 @@ files:
124
124
  - lib/miga/cli/action/date.rb
125
125
  - lib/miga/cli/action/derep_wf.rb
126
126
  - lib/miga/cli/action/doctor.rb
127
+ - lib/miga/cli/action/doctor/base.rb
127
128
  - lib/miga/cli/action/edit.rb
128
129
  - lib/miga/cli/action/files.rb
129
130
  - lib/miga/cli/action/find.rb