Class: MiGA::Result

Inherits:
MiGA
  • Object
show all
Includes:
Dates, Source, Stats
Defined in:
lib/miga/result.rb,
lib/miga/result/base.rb

Overview

The result from a task run. It can be project-wide or dataset-specific.

Defined Under Namespace

Modules: Base, Dates, Source, Stats

Constant Summary

Constants included from MiGA

CITATION, VERSION, VERSION_DATE, VERSION_NAME

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Stats

#compute_stats, #stats

Methods included from Source

#key, #project, #project_path, #relative_dir, #relative_path, #source

Methods included from Dates

#done_at, #running_time, #started_at

Methods inherited from MiGA

CITATION, CITATION_ARRAY, DEBUG, DEBUG_OFF, DEBUG_ON, DEBUG_TRACE_OFF, DEBUG_TRACE_ON, FULL_VERSION, LONG_VERSION, VERSION, VERSION_DATE, #advance, debug?, debug_trace?, initialized?, #like_io?, #num_suffix, rc_path, #result_files_exist?, #say

Methods included from Common::Path

#root_path, #script_path

Methods included from Common::Format

#clean_fasta_file, #seqs_length, #tabulate

Methods included from Common::Net

#download_file_ftp, #known_hosts, #remote_connection

Methods included from Common::SystemCall

#run_cmd, #run_cmd_opts

Constructor Details

#initialize(path) ⇒ Result

Load or create the MiGA::Result described by the JSON file path



53
54
55
56
# File 'lib/miga/result.rb', line 53

def initialize(path)
  @path = File.absolute_path(path)
  MiGA::Result.exist?(@path) ? load : create
end

Instance Attribute Details

#dataObject (readonly)

Hash with the result metadata



49
50
51
# File 'lib/miga/result.rb', line 49

def data
  @data
end

Class Method Details

.create(path, force = false) ⇒ Object

Check if path describes a result and otherwise create it using the passed block. If force, ignore existing JSON in path if any.



35
36
37
38
39
40
41
42
# File 'lib/miga/result.rb', line 35

def create(path, force = false)
  FileUtils.rm(path) if force && File.exist?(path)
  r_pre = load(path)
  return r_pre unless r_pre.nil?

  yield
  load(path)
end

.exist?(path) ⇒ Boolean

Check if the result described by the JSON in path already exists

Returns:

  • (Boolean)


18
19
20
# File 'lib/miga/result.rb', line 18

def exist?(path)
  File.exist? path
end

.load(path) ⇒ Object

Load the result described by the JSON in path. Returns MiGA::Result if it already exists, nil otherwise.



25
26
27
28
29
# File 'lib/miga/result.rb', line 25

def load(path)
  return nil unless MiGA::Result.exist? path

  MiGA::Result.new(path)
end

.RESULT_DIRSObject



3
4
5
6
# File 'lib/miga/result/base.rb', line 3

def RESULT_DIRS
  @@RESULT_DIRS ||=
    MiGA::Dataset.RESULT_DIRS.merge(MiGA::Project.RESULT_DIRS)
end

Instance Method Details

#[](k) ⇒ Object

Entry with symbol k



123
124
125
# File 'lib/miga/result.rb', line 123

def [](k)
  data[k.to_sym]
end

#[]=(k, v) ⇒ Object

Adds value v to entry with symbol k



129
130
131
# File 'lib/miga/result.rb', line 129

def []=(k, v)
  data[k.to_sym] = v
end

#add_file(k, file) ⇒ Object

Register file (path relative to #dir) with the symbol k. If the file doesn’t exist but the .gz extension does, the gzipped file is registered instead. If neither exists, nothing is registered.



137
138
139
140
141
142
143
# File 'lib/miga/result.rb', line 137

def add_file(k, file)
  k = k.to_sym
  @data[:files] ||= {}
  @data[:files][k] = file if File.exist? File.expand_path(file, dir)
  @data[:files][k] = "#{file}.gz" if
    File.exist? File.expand_path("#{file}.gz", dir)
end

#add_files(files) ⇒ Object

#add_file for each key-value pair in the files Hash



147
148
149
# File 'lib/miga/result.rb', line 147

def add_files(files)
  files.each { |k, v| add_file(k, v) }
end

#clean!Object

Register the result as cleaned, returns self



66
67
68
69
# File 'lib/miga/result.rb', line 66

def clean!
  self[:clean] = true
  self
end

#clean?Boolean

Is the result clean? Returns Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/miga/result.rb', line 60

def clean?
  !!self[:clean]
end

#createObject

Initialize and #save empty result



153
154
155
156
# File 'lib/miga/result.rb', line 153

def create
  @data = { created: Time.now.to_s, stats: {}, files: {} }
  save
end

#dir(relative = false) ⇒ Object

Directory containing the result; by default an absolute path, if relative is true returns the path relative to the parent project



105
106
107
# File 'lib/miga/result.rb', line 105

def dir(relative = false)
  relative ? relative_dir : File.dirname(path)
end

#each_file(&blk) ⇒ Object

Iterate blk for each registered file. Depending on the number of arguments of blk (arity), it’s called as:

  • blk

  • blk[file_sym, file_rel]

  • blk[file_sym, file_rel, file_abs]

Note that multiple files may have the same symbol (file_sym), since arrays of files are supported.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/miga/result.rb', line 201

def each_file(&blk)
  return to_enum(:each_file) unless block_given?

  @data[:files] ||= {}
  self[:files].each do |k, files|
    files = [files] unless files.is_a? Array
    files.each do |file|
      case blk.arity
      when 1 then blk.call(file)
      when 2 then blk.call(k, file)
      when 3 then blk.call(k, file, File.expand_path(file, dir))
      else
        raise "Wrong number of arguments: #{blk.arity} for 1..3"
      end
    end
  end
end

#file_path(k, relative = false) ⇒ Object

Absolute path to the file(s) defined by symbol k, or relative path if relative is true



112
113
114
115
116
117
118
119
# File 'lib/miga/result.rb', line 112

def file_path(k, relative = false)
  k = k.to_sym
  f = self[:files].nil? ? nil : self[:files][k]
  return nil if f.nil?
  return File.join(dir(relative), f) unless f.is_a? Array

  f.map { |fi| File.join(dir(relative), fi) }
end

#loadObject

Load (or reload) result data in the JSON file #path



173
174
175
176
# File 'lib/miga/result.rb', line 173

def load
  @data = MiGA::Json.parse(path)
  @data[:files] ||= {}
end

#path(which = :json) ⇒ Object

Path to the standard files of the result. which must be one of:

  • :json (default) : JSON file describing the result.

  • :start : File with the date when the processing started.

  • :done : File with the date when the processing ended.



91
92
93
94
95
96
97
98
99
100
# File 'lib/miga/result.rb', line 91

def path(which = :json)
  case which.to_sym
  when :json
    @path
  when :start
    @path.sub(/\.json$/, '.start')
  when :done
    @path.sub(/\.json$/, '.done')
  end
end

#recalculate!(reason = nil) ⇒ Object

Mark the result to be recalculated, returns self



79
80
81
82
83
84
# File 'lib/miga/result.rb', line 79

def recalculate!(reason = nil)
  self[:recalculate] = true
  self[:recalculate_why] = reason
  self[:recalculate_when] = Time.now.to_s
  self
end

#recalculate?Boolean

Is the result marked to be recalculated? Returns Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/miga/result.rb', line 73

def recalculate?
  !!self[:recalculate]
end

#remove!Object

Remove result, including all associated files



180
181
182
183
# File 'lib/miga/result.rb', line 180

def remove!
  each_file { |file| FileUtils.rm_rf(File.join(dir, file)) }
  unlink
end

#saveObject

Save the result persistently (in the JSON file #path)



160
161
162
163
164
165
166
167
168
169
# File 'lib/miga/result.rb', line 160

def save
  @data[:updated] = Time.now.to_s
  s = path(:start)
  if File.exist? s
    @data[:started] = File.read(s).chomp
    File.unlink s
  end
  MiGA::Json.generate(data, path)
  load
end

Unlink result by removing the .done and .start timestamps and the .json descriptor, but don’t remove any other associated files



187
188
189
190
191
# File 'lib/miga/result.rb', line 187

def unlink
  %i[start done json].each do |i|
    f = path(i) and File.exist?(f) and File.unlink(f)
  end
end