miga-base 0.2.0.9 → 0.2.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/actions/add_result.rb +37 -0
  4. data/actions/add_taxonomy.rb +63 -0
  5. data/actions/create_dataset.rb +49 -0
  6. data/actions/create_project.rb +46 -0
  7. data/actions/daemon.rb +50 -0
  8. data/actions/date.rb +14 -0
  9. data/actions/{download_dataset → download_dataset.rb} +5 -28
  10. data/actions/find_datasets.rb +41 -0
  11. data/actions/import_datasets.rb +47 -0
  12. data/actions/index_taxonomy.rb +46 -0
  13. data/actions/list_datasets.rb +50 -0
  14. data/actions/list_files.rb +43 -0
  15. data/actions/project_info.rb +40 -0
  16. data/actions/unlink_dataset.rb +28 -0
  17. data/bin/miga +129 -33
  18. data/lib/miga/daemon.rb +48 -34
  19. data/lib/miga/dataset.rb +7 -123
  20. data/lib/miga/dataset_result.rb +177 -0
  21. data/lib/miga/project.rb +32 -12
  22. data/lib/miga/version.rb +2 -2
  23. data/scripts/_distances_functions.bash +82 -0
  24. data/scripts/_distances_noref_nomulti.bash +96 -67
  25. data/scripts/_distances_ref_nomulti.bash +54 -85
  26. data/scripts/assembly.bash +16 -3
  27. data/scripts/clade_finding.bash +20 -18
  28. data/scripts/distances.bash +2 -1
  29. data/scripts/init.bash +2 -6
  30. data/scripts/subclades.bash +4 -5
  31. data/test/common_test.rb +2 -2
  32. data/test/daemon_test.rb +73 -1
  33. data/test/project_test.rb +26 -2
  34. data/test/taxonomy_test.rb +10 -0
  35. data/test/test_helper.rb +1 -1
  36. data/utils/subclades-compile.rb +4 -2
  37. data/utils/subclades.R +140 -158
  38. metadata +48 -44
  39. data/actions/add_result +0 -58
  40. data/actions/add_taxonomy +0 -83
  41. data/actions/create_dataset +0 -61
  42. data/actions/create_project +0 -67
  43. data/actions/daemon +0 -66
  44. data/actions/find_datasets +0 -61
  45. data/actions/import_datasets +0 -83
  46. data/actions/index_taxonomy +0 -68
  47. data/actions/list_datasets +0 -81
  48. data/actions/list_files +0 -63
  49. data/actions/unlink_dataset +0 -49
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # @package MiGA
4
+ # @license Artistic-2.0
5
+
6
+ require "miga/tax_index"
7
+
8
+ o = {q:true, format: :json}
9
+ OptionParser.new do |opt|
10
+ opt_banner(opt)
11
+ opt_object(opt, o, [:project])
12
+ opt.on("-i", "--index PATH",
13
+ "(Mandatory) File to create with the index."){ |v| o[:index]=v }
14
+ opt.on("-f", "--format STRING",
15
+ "Format of the index file. By default: #{o[:format]}. Supported: " +
16
+ "json, tab."){ |v| o[:format]=v.to_sym }
17
+ opt_filter_datasets(opt, o)
18
+ opt_common(opt, o)
19
+ end.parse!
20
+
21
+ ##=> Main <=
22
+ opt_require(o, project:"-P", index:"-i")
23
+
24
+ $stderr.puts "Loading project." unless o[:q]
25
+ p = MiGA::Project.load(o[:project])
26
+ raise "Impossible to load project: #{o[:project]}" if p.nil?
27
+
28
+ $stderr.puts "Loading datasets." unless o[:q]
29
+ ds = p.datasets
30
+ ds.select!{|d| not d.metadata[:tax].nil? }
31
+ ds = filter_datasets!(ds, o)
32
+
33
+ $stderr.puts "Indexing taxonomy." unless o[:q]
34
+ tax_index = MiGA::TaxIndex.new
35
+ ds.each { |d| tax_index << d }
36
+
37
+ $stderr.puts "Saving index." unless o[:q]
38
+ fh = File.open(o[:index], "w")
39
+ if o[:format]==:json
40
+ fh.print tax_index.to_json
41
+ elsif o[:format]==:tab
42
+ fh.print tax_index.to_tab
43
+ end
44
+ fh.close
45
+
46
+ $stderr.puts "Done." unless o[:q]
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # @package MiGA
4
+ # @license Artistic-2.0
5
+
6
+ o = {q:true, info:false, processing:false}
7
+ OptionParser.new do |opt|
8
+ opt_banner(opt)
9
+ opt_object(opt, o, [:project, :dataset_opt])
10
+ opt_filter_datasets(opt, o)
11
+ opt.on("-i", "--info",
12
+ "Print additional information on each dataset."){ |v| o[:info]=v }
13
+ opt.on("-p", "--processing",
14
+ "Print information on processing advance."){ |v| o[:processing]=v }
15
+ opt.on("-m", "--metadata STRING",
16
+ "Print name and metadata field only. If set, ignores -i."
17
+ ){ |v| o[:datum]=v }
18
+ opt_common(opt, o)
19
+ end.parse!
20
+
21
+ ##=> Main <=
22
+ opt_require(o, project:"-P")
23
+
24
+ $stderr.puts "Loading project." unless o[:q]
25
+ p = MiGA::Project.load(o[:project])
26
+ raise "Impossible to load project: #{o[:project]}" if p.nil?
27
+
28
+ $stderr.puts "Listing datasets." unless o[:q]
29
+ if o[:dataset].nil?
30
+ ds = p.datasets
31
+ elsif MiGA::Dataset.exist? p, o[:dataset]
32
+ ds = [p.dataset(o[:dataset])]
33
+ else
34
+ ds = []
35
+ end
36
+ ds = filter_datasets!(ds, o)
37
+
38
+ if not o[:datum].nil?
39
+ ds.each{|d| puts "#{d.name}\t#{d.metadata[ o[:datum] ] || "?"}"}
40
+ elsif o[:info]
41
+ puts MiGA::MiGA.tabulate(MiGA::Dataset.INFO_FIELDS, ds.map{ |d| d.info })
42
+ elsif o[:processing]
43
+ comp = ["undef","done","queued"]
44
+ puts MiGA::MiGA.tabulate([:name] + MiGA::Dataset.PREPROCESSING_TASKS,
45
+ ds.map{ |d| [d.name] + d.profile_advance.map{ |i| comp[i] } })
46
+ else
47
+ ds.each{|d| puts d.name}
48
+ end
49
+
50
+ $stderr.puts "Done." unless o[:q]
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # @package MiGA
4
+ # @license Artistic-2.0
5
+
6
+ o = {q:true, details:false, json:true}
7
+ OptionParser.new do |opt|
8
+ opt_banner(opt)
9
+ opt_object(opt, o, [:project, :dataset_opt])
10
+ opt.on("-i", "--info",
11
+ "If set, it prints additional details for each file."
12
+ ){ |v| o[:details]=v }
13
+ opt.on("--[no-]json",
14
+ "If set to no, excludes json files containing results metadata."
15
+ ){ |v| o[:json]=v }
16
+ opt_common(opt, o)
17
+ end.parse!
18
+
19
+ ##=> Main <=
20
+ opt_require(o, project:"-P")
21
+
22
+ $stderr.puts "Loading project." unless o[:q]
23
+ p = MiGA::Project.load(o[:project])
24
+ raise "Impossible to load project: #{o[:project]}" if p.nil?
25
+
26
+ if o[:dataset].nil?
27
+ results = p.results
28
+ else
29
+ $stderr.puts "Loading dataset." unless o[:q]
30
+ ds = p.dataset(o[:dataset])
31
+ raise "Impossible to load dataset: #{o[:dataset]}" if ds.nil?
32
+ results = ds.results
33
+ end
34
+
35
+ $stderr.puts "Listing files." unless o[:q]
36
+ results.each do |result|
37
+ puts "#{ "#{result.path}\t\t" if o[:details] }#{result.path}" if o[:json]
38
+ result.each_file do |k,f|
39
+ puts "#{ "#{result.path}\t#{k}\t" if o[:details] }#{result.dir}/#{f}"
40
+ end
41
+ end
42
+
43
+ $stderr.puts "Done." unless o[:q]
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # @package MiGA
4
+ # @license Artistic-2.0
5
+
6
+ o = {q:true, info:false, processing:false}
7
+ OptionParser.new do |opt|
8
+ opt_banner(opt)
9
+ opt_object(opt, o, [:project])
10
+ opt.on("-p", "--processing",
11
+ "Print information on processing advance."){ |v| o[:processing]=v }
12
+ opt.on("-m", "--metadata STRING",
13
+ "Print name and metadata field only. If set, ignores -i."
14
+ ){ |v| o[:datum]=v }
15
+ opt_common(opt, o)
16
+ end.parse!
17
+
18
+
19
+ ##=> Main <=
20
+ opt_require(o, project:"-P")
21
+
22
+ $stderr.puts "Loading project." unless o[:q]
23
+ p = MiGA::Project.load(o[:project])
24
+ raise "Impossible to load project: #{o[:project]}" if p.nil?
25
+
26
+ if not o[:datum].nil?
27
+ puts (p.metadata[ o[:datum] ] || "?")
28
+ elsif o[:processing]
29
+ keys = MiGA::Project.DISTANCE_TASKS + MiGA::Project.INCLADE_TASKS
30
+ puts MiGA::MiGA.tabulate([:task, :status], keys.map do |k|
31
+ [k, p.add_result(k, false).nil? ? "queued" : "done"]
32
+ end)
33
+ else
34
+ puts MiGA::MiGA.tabulate([:key, :value], p.metadata.data.keys.map do |k|
35
+ v = p.metadata[k]
36
+ [k, k==:datasets ? v.size : v]
37
+ end)
38
+ end
39
+
40
+ $stderr.puts "Done." unless o[:q]
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # @package MiGA
4
+ # @license Artistic-2.0
5
+
6
+ o = {q:true, remove:false}
7
+ OptionParser.new do |opt|
8
+ opt_banner(opt)
9
+ opt_object(opt, o)
10
+ opt.on("-r", "--remove", "Also remove all associated files.",
11
+ "By default, only unlinks from metadata."){ o[:remove]=true }
12
+ opt_common(opt, o)
13
+ end.parse!
14
+
15
+ ##=> Main <=
16
+ opt_require(o)
17
+
18
+ $stderr.puts "Loading project." unless o[:q]
19
+ p = MiGA::Project.load(o[:project])
20
+ raise "Impossible to load project: #{o[:project]}" if p.nil?
21
+
22
+ $stderr.puts "Unlinking dataset." unless o[:q]
23
+ raise "Dataset doesn't exist, aborting." unless
24
+ MiGA::Dataset.exist?(p, o[:dataset])
25
+ d = p.unlink_dataset(o[:dataset])
26
+ d.remove! if o[:remove]
27
+
28
+ $stderr.puts "Done." unless o[:q]
data/bin/miga CHANGED
@@ -1,48 +1,144 @@
1
1
  #!/usr/bin/env ruby
2
- #
2
+
3
3
  # @package MiGA
4
- # @author Luis M. Rodriguez-R <lmrodriguezr at gmail dot com>
5
- # @license artistic license 2.0
6
- # @update Oct-01-2015
7
- #
4
+ # @license Artistic-2.0
8
5
 
9
6
  $:.push File.expand_path("../lib", File.dirname(__FILE__))
10
7
 
11
8
  require "optparse"
12
9
  require "miga"
13
10
 
14
- execs = Dir[File.expand_path("../actions/*",
15
- File.dirname(__FILE__))].map{ |b| File.basename b }
16
-
17
- if %w{-v --version}.include? ARGV[0]
18
- puts MiGA::MiGA.VERSION
19
- elsif %w{-V --long-version}.include? ARGV[0]
20
- puts MiGA::MiGA.LONG_VERSION
21
- elsif %w{-C --citation}.include? ARGV[0]
22
- puts MiGA::MiGA.CITATION
23
- elsif execs.include? ARGV[0]
24
- task = ARGV.shift
25
- ARGV << "-h" if ARGV.empty?
26
- begin
27
- load File.expand_path("../actions/" + task, File.dirname(__FILE__))
28
- rescue => err
29
- $stderr.puts "Exception: #{err}\n\n"
30
- err.backtrace.each { |l| $stderr.puts l + "\n" }
31
- err
32
- end
11
+ ##=> Global variables <=
12
+
13
+ $task_desc = {
14
+ add_result: "Registers a result.",
15
+ add_taxonomy: "Registers taxonomic information for datasets.",
16
+ create_dataset: "Creates an empty dataset in a pre-existing MiGA project.",
17
+ create_project: "Creates an empty MiGA project.",
18
+ daemon: "Controls the daemon of a MiGA project.",
19
+ date: "Returns the current date in standard MiGA format.",
20
+ download_dataset: "Creates an empty dataset in a pre-existing MiGA project.",
21
+ find_datasets: "Finds unregistered datasets based on result files.",
22
+ import_datasets: "Link datasets (including results) from one project to "+
23
+ "another.",
24
+ index_taxonomy: "Creates a taxonomy-indexed list of the datasets.",
25
+ list_datasets: "Lists all registered datasets in an MiGA project.",
26
+ list_files: "Lists all registered files from the results of a dataset or a "+
27
+ "project.",
28
+ project_info: "Displays information about a MiGA project.",
29
+ unlink_dataset: "Removes a dataset from an MiGA project."
30
+ }
31
+
32
+ ##=> Functions <=
33
+
34
+ # OptParse banner
35
+ def opt_banner(opt)
36
+ opt.banner = <<BAN
37
+ #{$task_desc[$task]}
38
+
39
+ Usage: #{$0} #{$task} [options]
40
+ BAN
41
+ opt.separator ""
42
+ end
43
+
44
+ # OptParse flags that determine the object to load
45
+ def opt_object(opt, o, what=[:project, :dataset])
46
+ opt.on("-P", "--project PATH", "(Mandatory) Path to the project."
47
+ ){ |v| o[:project]=v } if what.include? :project
48
+ opt.on("-D", "--dataset PATH", "(Mandatory) Name of the dataset."
49
+ ){ |v| o[:dataset]=v } if what.include? :dataset
50
+ opt.on("-D", "--dataset PATH", "Name of the dataset."
51
+ ){ |v| o[:dataset]=v } if what.include? :dataset_opt
52
+ opt.on("-t", "--type STRING",
53
+ "Type of dataset. Recognized types include:",
54
+ *MiGA::Dataset.KNOWN_TYPES.map{ |k,v| "~ #{k}: #{v[:description]}" }
55
+ ){ |v| o[:type]=v.to_sym } if what.include? :dataset_type
56
+ opt.on("-t", "--type STRING",
57
+ "Type of dataset. Recognized types include:",
58
+ *MiGA::Project.KNOWN_TYPES.map{ |k,v| "~ #{k}: #{v[:description]}"}
59
+ ){ |v| o[:type]=v.to_sym } if what.include? :project_type
60
+ end
61
+
62
+ # OptParse flags common to all actions.
63
+ def opt_common(opt, o)
64
+ opt.on("-v", "--verbose",
65
+ "Print additional information to STDERR."){ o[:q]=false }
66
+ opt.on("-d", "--debug INT", "Print debugging information to STDERR.") do |v|
67
+ v.to_i>1 ? MiGA::MiGA.DEBUG_TRACE_ON : MiGA::MiGA.DEBUG_ON
68
+ end
69
+ opt.on("-h", "--help", "Display this screen.") do
70
+ puts opt
71
+ exit
72
+ end
73
+ opt.separator ""
74
+ end
75
+
76
+ # OptParse flags to filter lists of datasets.
77
+ def opt_filter_datasets(opt, o, what=[:ref, :multi, :taxonomy])
78
+ opt.on("--[no-]ref",
79
+ "If set, uses only reference (or only non-reference) datasets."
80
+ ){ |v| o[:ref]=v } if what.include? :ref
81
+ opt.on("--[no-]multi",
82
+ "If set, uses only multi-species (or only single-species) datasets."
83
+ ){ |v| o[:multi]=v } if what.include? :multi
84
+ opt.on("-t", "--taxonomy RANK:TAXON", "Filter by taxonomy."
85
+ ){ |v| o[:taxonomy]=MiGA::Taxonomy.new v } if what.include? :taxonomy
86
+ end
87
+
88
+ def opt_require(o, req={project:"-P", dataset:"-D"})
89
+ req.each do |k,v|
90
+ raise "#{v} is mandatory: please provide #{k}." if o[k].nil?
91
+ end
92
+ end
93
+
94
+ # Filters datasets by keys set in +opt_filter_datasets+.
95
+ def filter_datasets!(ds, o)
96
+ ds.select!{|d| d.is_ref? == o[:ref] } unless o[:ref].nil?
97
+ ds.select! do |d|
98
+ o[:multi] ? d.is_multi? : d.is_nonmulti?
99
+ end unless o[:multi].nil?
100
+ ds.select! do |d|
101
+ (not d.metadata[:tax].nil?) and d.metadata[:tax].is_in?(o[:taxonomy])
102
+ end unless o[:taxonomy].nil?
103
+ ds
104
+ end
105
+
106
+ ##=> Main <=
107
+
108
+ execs = $task_desc.keys.map{ |k| k.to_s }
109
+
110
+ case ARGV[0]
111
+ when "-v", "--version"
112
+ puts MiGA::MiGA.VERSION
113
+ when "-V", "--long-version"
114
+ puts MiGA::MiGA.LONG_VERSION
115
+ when "-C", "--citation"
116
+ puts MiGA::MiGA.CITATION
117
+ when *execs
118
+ $task = ARGV.shift.to_sym
119
+ ARGV << "-h" if ARGV.empty? and not [:date].include? $task
120
+ begin
121
+ load File.expand_path("../actions/#{$task}.rb", File.dirname(__FILE__))
122
+ rescue => err
123
+ $stderr.puts "Exception: #{err}\n\n"
124
+ err.backtrace.each { |l| $stderr.puts l + "\n" }
125
+ err
126
+ end
33
127
  else
34
- print <<HELP.gsub(/^ /,"")
35
- Microbial Genomes Atlas.
128
+ print <<HELP
129
+
130
+ Microbial Genomes Atlas.
131
+
132
+ Usage: #{$0} {action} [options]
36
133
 
37
- Usage: #{$0} {action} [options]
134
+ #{ MiGA::MiGA.tabulate([:action, :description], $task_desc.to_a).join("\n")}
38
135
 
39
- actions:#{ execs.map{ |e| "\n #{e}"}.join }
136
+ generic options:
137
+ -h, --help Display this screen.
138
+ -v, --version Show MiGA version.
139
+ -V, --long-version Show complete MiGA version.
140
+ -C, --citation How to cite MiGA.
40
141
 
41
- generic options:
42
- -h, --help Display this screen.
43
- -v, --version Show MiGA version.
44
- -V, --long-version Show complete MiGA version.
45
- -C, --citation How to cite MiGA.
46
142
  HELP
47
143
  end
48
144
 
data/lib/miga/daemon.rb CHANGED
@@ -26,6 +26,8 @@ class MiGA::Daemon < MiGA::MiGA
26
26
  attr_reader :jobs_to_run
27
27
  # Array of jobs currently running.
28
28
  attr_reader :jobs_running
29
+ # Integer indicating the current iteration.
30
+ attr_reader :loop_i
29
31
 
30
32
  ##
31
33
  # Initialize an unactive daemon for the MiGA::Project +project+. See #daemon
@@ -37,6 +39,7 @@ class MiGA::Daemon < MiGA::MiGA
37
39
  {:symbolize_names=>true})
38
40
  @jobs_to_run = []
39
41
  @jobs_running = []
42
+ @loop_i = -1
40
43
  end
41
44
 
42
45
  ##
@@ -55,13 +58,14 @@ class MiGA::Daemon < MiGA::MiGA
55
58
 
56
59
  ##
57
60
  # Set/get #options, where +k+ is the Symbol of the option and +v+ is the value
58
- # (or nil to use as getter). Returns new value.
59
- def runopts(k, v=nil)
61
+ # (or nil to use as getter). Skips consistency tests if +force+. Returns new
62
+ # value.
63
+ def runopts(k, v=nil, force=false)
60
64
  k = k.to_sym
61
65
  unless v.nil?
62
66
  v = v.to_i if [:latency, :maxjobs, :ppn].include? k
63
67
  raise "Daemon's #{k} cannot be set to zero." if
64
- v.is_a? Integer and v==0
68
+ !force and v.is_a? Integer and v==0
65
69
  @runopts[k] = v
66
70
  end
67
71
  @runopts[k]
@@ -80,20 +84,20 @@ class MiGA::Daemon < MiGA::MiGA
80
84
  def ppn() runopts(:ppn) ; end
81
85
 
82
86
  ##
83
- # Initializes the daemon.
84
- def start() daemon("start") ; end
87
+ # Initializes the daemon with +opts+.
88
+ def start(opts=[]) daemon("start", opts) ; end
85
89
 
86
90
  ##
87
- # Stops the daemon.
88
- def stop() daemon("stop") ; end
91
+ # Stops the daemon with +opts+.
92
+ def stop(opts=[]) daemon("stop", opts) ; end
89
93
 
90
94
  ##
91
- # Restarts the daemon.
92
- def restart() daemon("restart") ; end
95
+ # Restarts the daemon with +opts+.
96
+ def restart(opts=[]) daemon("restart", opts) ; end
93
97
 
94
98
  ##
95
- # Returns the status of the daemon.
96
- def status() daemon("status") ; end
99
+ # Returns the status of the daemon with +opts+.
100
+ def status(opts=[]) daemon("status", opts) ; end
97
101
 
98
102
  ##
99
103
  # Launches the +task+ with options +opts+ (as command-line arguments).
@@ -102,26 +106,7 @@ class MiGA::Daemon < MiGA::MiGA
102
106
  options = default_options
103
107
  opts.unshift(task)
104
108
  options[:ARGV] = opts
105
- Daemons.run_proc("MiGA:#{project.name}", options) do
106
- say "-----------------------------------"
107
- say "MiGA:#{project.name} launched."
108
- say "-----------------------------------"
109
- loop_i = 0
110
- loop do
111
- loop_i += 1
112
- declare_alive
113
- check_datasets
114
- check_project
115
- flush!
116
- if loop_i==12
117
- say "Housekeeping for sanity"
118
- loop_i = 0
119
- purge!
120
- project.load
121
- end
122
- sleep(latency)
123
- end
124
- end
109
+ Daemons.run_proc("MiGA:#{project.name}", options) { loop { in_loop } }
125
110
  end
126
111
 
127
112
  ##
@@ -135,9 +120,14 @@ class MiGA::Daemon < MiGA::MiGA
135
120
  ##
136
121
  # Traverse datasets
137
122
  def check_datasets
138
- project.each_dataset do |ds|
139
- to_run = ds.next_preprocessing(true)
140
- queue_job(to_run, ds) unless to_run.nil?
123
+ project.each_dataset do |n, ds|
124
+ if ds.nil?
125
+ say "Warning: Dataset #{n} listed but not loaded, reloading project."
126
+ project.load
127
+ else
128
+ to_run = ds.next_preprocessing(true)
129
+ queue_job(to_run, ds) unless to_run.nil?
130
+ end
141
131
  end
142
132
  end
143
133
 
@@ -145,6 +135,7 @@ class MiGA::Daemon < MiGA::MiGA
145
135
  # Check if all reference datasets are pre-processed. If yes, check the
146
136
  # project-level tasks
147
137
  def check_project
138
+ return if project.dataset_names.empty?
148
139
  if project.done_preprocessing?(false)
149
140
  to_run = project.next_distances(true)
150
141
  to_run = project.next_inclade(true) if to_run.nil?
@@ -230,6 +221,29 @@ class MiGA::Daemon < MiGA::MiGA
230
221
  end
231
222
  end
232
223
 
224
+ ##
225
+ # Run one loop step.
226
+ def in_loop
227
+ if loop_i == -1
228
+ say "-----------------------------------"
229
+ say "MiGA:#{project.name} launched."
230
+ say "-----------------------------------"
231
+ @loop_i = 0
232
+ end
233
+ @loop_i += 1
234
+ declare_alive
235
+ check_datasets
236
+ check_project
237
+ flush!
238
+ if loop_i==12
239
+ say "Housekeeping for sanity"
240
+ @loop_i = 0
241
+ purge!
242
+ project.load
243
+ end
244
+ sleep(latency)
245
+ end
246
+
233
247
  ##
234
248
  # Send a datestamped message to the log.
235
249
  def say(*opts)