Class: MiGA::Result

Inherits:
MiGA
  • Object
show all
Includes:
Dates, Source, Stats, Versions
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, Versions

Constant Summary

Constants included from MiGA

CITATION, VERSION, VERSION_DATE, VERSION_NAME

Instance Attribute Summary collapse

Attributes included from Common::Net

#remote_connection_uri

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Versions

#add_versions, #versions, #versions_md

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, #http_request, #known_hosts, #main_server, #net_method, #normalize_encoding, #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



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

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



63
64
65
# File 'lib/miga/result.rb', line 63

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, but it can rescue the versions field from the old one if it exists and the new one doesn’t contain such field.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/miga/result.rb', line 39

def create(path, force = false)
  # Deal with old results first
  r_old = load(path)
  return r_old if r_old && !force

  # Create the new result using the block passed
  FileUtils.rm(path) if r_old
  yield

  # Load and return
  load(path).tap do |r_new|
    # Rescue versions and start (if any and if necessary)
    if r_old
      %i[versions started].each { |i| r_new[i] ||= r_old[i] }
      r_new[:versions] = (r_old[:versions] || {}).merge(r_new[:versions])
    end
  end
end

.exist?(path) ⇒ Boolean

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

Returns:

  • (Boolean)


20
21
22
# File 'lib/miga/result.rb', line 20

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.



27
28
29
30
31
# File 'lib/miga/result.rb', line 27

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



137
138
139
# File 'lib/miga/result.rb', line 137

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

#[]=(k, v) ⇒ Object

Adds value v to entry with symbol k



143
144
145
# File 'lib/miga/result.rb', line 143

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.



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

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



161
162
163
# File 'lib/miga/result.rb', line 161

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

#clean!Object

Register the result as cleaned, returns self



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

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

#clean?Boolean

Is the result clean? Returns Boolean

Returns:

  • (Boolean)


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

def clean?
  !!self[:clean]
end

#createObject

Initialize and #save empty result



167
168
169
170
171
172
173
174
# File 'lib/miga/result.rb', line 167

def create
  @data = {
    created: Time.now.to_s,
    stats: {}, files: {},
    versions: { 'MiGA' => MiGA::VERSION.join('.') }
  }
  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



119
120
121
# File 'lib/miga/result.rb', line 119

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.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/miga/result.rb', line 219

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



126
127
128
129
130
131
132
133
# File 'lib/miga/result.rb', line 126

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



191
192
193
194
# File 'lib/miga/result.rb', line 191

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.



105
106
107
108
109
110
111
112
113
114
# File 'lib/miga/result.rb', line 105

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



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

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)


87
88
89
# File 'lib/miga/result.rb', line 87

def recalculate?
  !!self[:recalculate]
end

#remove!Object

Remove result, including all associated files



198
199
200
201
# File 'lib/miga/result.rb', line 198

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

#saveObject

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



178
179
180
181
182
183
184
185
186
187
# File 'lib/miga/result.rb', line 178

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



205
206
207
208
209
# File 'lib/miga/result.rb', line 205

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