biopsy 0.1.9 → 0.2.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
  SHA1:
3
- metadata.gz: cd71d61a677d1be5a428a38587f2a81a2215f3ef
4
- data.tar.gz: ce06d5dd2fadae096a852560cff2093fc5db249c
3
+ metadata.gz: 4a78e571268545fdd69d110f2b789bb53fa5d100
4
+ data.tar.gz: 3255fd3579a242fa6277c9b16d5128fe4d3c6250
5
5
  SHA512:
6
- metadata.gz: d400127139fdd1c30a39e1304fd23ebe87cc95bbb2ac0f304de3492057a5b27069f038dfe7940ecc03c89a5311ccdf2d234a5420d3e9d8b1530607f053023e2b
7
- data.tar.gz: 3145eb5f5826d1e90745986e1305eff1f10eb327a74107077dee0807d1f8735281ce056edf9e43b9e567442afa94122b0dcc512264ca4877f2e28f31f92f3fdd
6
+ metadata.gz: dd5c793e5af0042dd69066de1c96695e519d619a8738ad066baefc0d3015dc89ec6247d573090263f45ad3f78ea2bb8fa3df17945197d29bd48b23cee84556bc
7
+ data.tar.gz: 6a9d2b2dcc4463c1ad8afe3311af4b3912b0263f53c7b1aa609a16319aa5c2348c62a3c48b4caaf7760fa6e0d18df1423644772d7bde2285e10b866f223e4aed
@@ -18,10 +18,12 @@ module Biopsy
18
18
 
19
19
  class Experiment
20
20
 
21
- attr_reader :inputs, :outputs, :retain_intermediates, :target, :start, :algorithm
21
+ attr_reader :inputs, :outputs, :retain_intermediates
22
+ attr_reader :target, :start, :algorithm
22
23
 
23
24
  # Returns a new Experiment
24
- def initialize(target, options:{}, threads:4, start:nil, algorithm:nil, verbosity: :quiet)
25
+ def initialize(target, options:{}, threads:4, start:nil, algorithm:nil,
26
+ verbosity: :quiet)
25
27
  @threads = threads
26
28
  @start = start
27
29
  @algorithm = algorithm
@@ -51,12 +53,12 @@ module Biopsy
51
53
 
52
54
  # Return a random set of parameters from the parameter space.
53
55
  def random_start_point
54
- Hash[@target.parameters.map { |p, r| [p, r.sample] }]
56
+ Hash[@target.parameters.map { |p, r| [p, r.sample] }]
55
57
  end
56
58
 
57
59
  # select the optimisation algorithm to use
58
60
  def select_algorithm
59
- return if !algorithm.nil?
61
+ return if algorithm
60
62
  max = Settings.instance.sweep_cutoff
61
63
  n = @target.count_parameter_permutations
62
64
  if n < max
@@ -67,7 +69,7 @@ module Biopsy
67
69
  end
68
70
 
69
71
  # load the target named +:target_name+
70
- def load_target target_name
72
+ def load_target(target_name)
71
73
  @target = Target.new
72
74
  @target.load_by_name target_name
73
75
  end
@@ -79,21 +81,27 @@ module Biopsy
79
81
  in_progress = true
80
82
  @algorithm.setup @start
81
83
  @current_params = @start
82
- while in_progress do
84
+ while in_progress
83
85
  run_iteration
84
86
  # update the best result
85
87
  best = @best
86
88
  @best = @algorithm.best
87
89
  ptext = @best[:parameters].each_pair.map{ |k, v| "#{k}:#{v}" }.join(", ")
88
- if (@best && @best.has_key?(:score) && best && best.has_key?(:score) && @best[:score] > best[:score])
89
- puts "found a new best score: #{@best[:score]} for parameters #{ptext}" unless @verbosity == :silent
90
+ if @best &&
91
+ @best.key?(:score) &&
92
+ best &&
93
+ best.key?(:score) &&
94
+ @best[:score] > best[:score]
95
+ puts "found a new best score: #{@best[:score]} \
96
+ for parameters #{ptext}"
90
97
  end
91
98
  # have we finished?
92
99
  in_progress = !@algorithm.finished?
93
100
  end
94
101
  @algorithm.write_data if @algorithm.respond_to? :write_data
95
102
  unless @verbosity == :silent
96
- puts "found optimum score: #{@best[:score]} for parameters #{@best[:parameters]} in #{@iteration_count} iterations."
103
+ puts "found optimum score: #{@best[:score]} for parameters \
104
+ #{@best[:parameters]} in #{@iteration_count} iterations."
97
105
  end
98
106
  return @best
99
107
  end
@@ -103,16 +111,16 @@ module Biopsy
103
111
  # Returns the output of the optimiser.
104
112
  def run_iteration
105
113
  # create temp dir
106
- Dir.chdir(self.create_tempdir) do
114
+ Dir.chdir(self.create_tempdir) do
107
115
  # run the target
108
116
  raw_output = @target.run @current_params.merge(@options)
109
117
  # evaluate with objectives
110
118
  param_key = @current_params.to_s
111
119
  result = nil
112
- if @scores.has_key? param_key
120
+ if @scores.key? param_key
113
121
  result = @scores[param_key]
114
122
  else
115
- result = @objective.run_for_output(raw_output, @threads)
123
+ result = @objective.run_for_output(raw_output, @threads, nil)
116
124
  @iteration_count += 1
117
125
  self.print_progress(@iteration_count, @current_params, result, @best)
118
126
  end
@@ -135,17 +143,21 @@ module Biopsy
135
143
  def cleanup
136
144
  # TODO: make this work
137
145
  # remove all but essential files
146
+ essential_files = ""
138
147
  if Settings.instance.keep_intermediates
139
- @objectives.values.each{ |objective| essential_files += objective.essential_files }
148
+ # @objectives isn't mentioned anywhere in the rest of this file
149
+ @objectives.values.each do |objective|
150
+ essential_files += objective.essential_files
151
+ end
140
152
  end
141
153
  Dir["*"].each do |file|
142
154
  next
143
155
  # TODO: implement this
144
- next if File.directory? file
145
- if essential_files && essential_files.include?(file)
146
- `gzip #{file}` if Settings.instance.gzip_intermediates
147
- FileUtils.mv("#{file}.gz", '../output')
148
- end
156
+ # next if File.directory? file
157
+ # if essential_files && essential_files.include?(file)
158
+ # `gzip #{file}` if Settings.instance.gzip_intermediates
159
+ # FileUtils.mv("#{file}.gz", '../output')
160
+ # end
149
161
  end
150
162
  FileUtils.rm_rf @last_tempdir
151
163
  end
@@ -157,11 +169,11 @@ module Biopsy
157
169
  # generate random dirnames until we find one that
158
170
  # doesn't exist
159
171
  test_token = SecureRandom.hex
160
- break test_token unless File.exists? test_token
172
+ break test_token unless File.exist? test_token
161
173
  end
162
174
  Dir.mkdir(token)
163
175
  @last_tempdir = token
164
- return token
176
+ token
165
177
  end
166
178
 
167
179
  end # end of class RunHandler
@@ -25,7 +25,7 @@ module Biopsy
25
25
  #
26
26
  # objective = ObjectiveFunction.new
27
27
  # result = objective.run('example.fasta')
28
- def run(assemblydata)
28
+ def run(raw_output, output_files, threads)
29
29
  raise NotImplementedError.new("You must implement a run method for each objective function")
30
30
  end
31
31
 
@@ -6,21 +6,25 @@ require 'fileutils'
6
6
  # == Description
7
7
  #
8
8
  # The Handler manages the objective functions for the optimisation experiment.
9
- # Specifically, it finds all the objective functions and runs them when requested,
10
- # outputting the results to the main Optimiser.
9
+ # Specifically, it finds all the objective functions and runs them when
10
+ # requested, outputting the results to the main Optimiser.
11
11
  #
12
12
  # == Explanation
13
13
  #
14
14
  # === Loading objective functions
15
15
  #
16
- # The Handler expects a directory containing objectives (by default it looks in *currentdir/objectives*).
16
+ # The Handler expects a directory containing objectives (by default it looks
17
+ # in *currentdir/objectives*).
17
18
  # The *objectives* directory should contain the following:
18
19
  #
19
- # * a *.rb* file for each objective function. The file should define a subclass of ObjectiveFunction
20
- # * (optionally) a file *objectives.txt* which lists the objective function files to use
20
+ # * a *.rb* file for each objective function. The file should define a subclass
21
+ # of ObjectiveFunction
22
+ # * (optionally) a file *objectives.txt* which lists the objective function
23
+ # files to use
21
24
  #
22
- # If the objectives.txt file is absent, the subset of objectives to use can be set directly in the Optimiser
23
- # , or if no such restriction is set, the whole set of objectives will be run.
25
+ # If the objectives.txt file is absent, the subset of objectives to use can be
26
+ # set directly in the Optimiser, or if no such restriction is set, the whole
27
+ # set of objectives will be run.
24
28
  #
25
29
  # Each file listed in *objectives.txt* is loaded if it exists.
26
30
  #
@@ -39,22 +43,30 @@ module Biopsy
39
43
  attr_reader :last_tempdir
40
44
  attr_accessor :objectives
41
45
 
42
- def initialize target
46
+ def initialize(target)
43
47
  @target = target
44
48
  @objectives_dir = Settings.instance.objectives_dir.first
45
49
  @objectives = {}
46
50
  $LOAD_PATH.unshift(@objectives_dir)
47
- @subset = Settings.instance.respond_to?(:objectives_subset) ? Settings.instance.objectives_subset : nil
48
- self.load_objectives
51
+ if Settings.instance.respond_to?(:objectives_subset)
52
+ @subset = Settings.instance.objectives_subset
53
+ else
54
+ @subset = nil
55
+ end
56
+ load_objectives
49
57
  # pass objective list back to caller
50
- return @objectives.keys
58
+ @objectives.keys
51
59
  end
52
60
 
53
61
  def load_objectives
54
62
  # load objectives
55
63
  # load subset list if available
56
64
  subset_file = @objectives_dir + '/objectives.txt'
57
- subset = File.exists?(subset_file) ? File.open(subset_file).readlines.map{ |l| l.strip } : nil
65
+ if File.exist?(subset_file)
66
+ subset = File.open(subset_file).readlines.map { |l| l.strip }
67
+ else
68
+ subset = nil
69
+ end
58
70
  subset = @subset if subset.nil?
59
71
  # parse in objectives
60
72
  Dir.chdir @objectives_dir do
@@ -63,7 +75,7 @@ module Biopsy
63
75
  require file_name
64
76
  objective_name = file_name.camelize
65
77
  objective = Module.const_get(objective_name).new
66
- if subset.nil? or subset.include?(file_name)
78
+ if subset.nil? || subset.include?(file_name)
67
79
  # this objective is included
68
80
  @objectives[objective_name] = objective
69
81
  end
@@ -74,47 +86,49 @@ module Biopsy
74
86
 
75
87
  # Run a specific +:objective+ on the +:output+ of a target
76
88
  # with max +:threads+.
77
- def run_objective(objective, name, raw_output, output_files, threads)
78
- begin
79
- # output is a, array: [raw_output, output_files].
80
- # output_files is a hash containing the absolute paths
81
- # to file(s) output by the target in the format expected by the
82
- # objective function(s), with keys as the keys expected by the
83
- # objective function
84
- return objective.run(raw_output, output_files, threads)
85
- rescue NotImplementedError => e
86
- puts "Error: objective function #{objective.class} does not implement the run() method"
87
- puts "Please refer to the documentation for instructions on adding objective functions"
88
- raise e
89
- end
89
+ def run_objective(objective, _name, raw_output, output_files, threads)
90
+ # output is a, array: [raw_output, output_files].
91
+ # output_files is a hash containing the absolute paths
92
+ # to file(s) output by the target in the format expected by the
93
+ # objective function(s), with keys as the keys expected by the
94
+ # objective function
95
+ return objective.run(raw_output, output_files, threads)
96
+ rescue
97
+ error = "Error: objective function #{objective.class} does not "
98
+ error << "implement the run() method\nPlease refer to the "
99
+ error << "documentation for instructions on adding objective functions"
100
+ # raise NotImplementedError.new("message")
101
+ raise NotImplementedError, error
90
102
  end
91
103
 
92
104
  # Perform a euclidean distance dimension reduction of multiple objectives
93
105
  def dimension_reduce(results)
94
106
  # calculate the weighted Euclidean distance from optimal
95
- # d(p, q) = \sqrt{(p_1 - q_1)^2 + (p_2 - q_2)^2+...+(p_i - q_i)^2+...+(p_n - q_n)^2}
96
- # here the max value is sqrt(n) where n is no. of results, min value (optimum) is 0
107
+ # d(p, q) = \sqrt{(p_1 - q_1)^2 + (p_2 - q_2)^2+...+(p_n - q_n)^2}
108
+ # here the max value is sqrt(n) where n is no. of results,
109
+ # min value (optimum) is 0
97
110
  total = 0
98
- results.each_pair do |key, value|
111
+ results.each_value do |value|
99
112
  o = value[:optimum]
100
113
  w = value[:weighting]
101
114
  a = value[:result]
102
115
  m = value[:max]
103
- total += w * (((o - a)/m) ** 2)
116
+ total += w * (((o - a) / m)**2) if m != 0
104
117
  end
105
- return Math.sqrt(total) / results.length
118
+ Math.sqrt(total) / results.length
106
119
  end
107
120
 
108
- # Run all objectives functions for +:output+.
109
- def run_for_output(raw_output, threads=6, allresults=false)
121
+ # Run all objectives functions for +:output+.
122
+ def run_for_output(raw_output, threads, allresults)
110
123
  # check output files exist
111
124
  output_files = {}
112
125
  @target.output.each_pair do |key, glob|
113
126
  files = Dir[glob]
114
- zerosize = files.reduce(false) { |empty, f| File.size(f) == 0 }
115
- if files.empty? || zerosize
116
- puts ObjectiveHandlerError.new "output files for #{key} matching #{glob} do not exist or are empty"
117
- return nil
127
+ size = files.reduce(1) { |sum, f| sum * File.size(f)}
128
+ if files.empty? || size==0
129
+ error = "output files for #{key} matching #{glob} do not exist" +
130
+ " or are empty"
131
+ raise ObjectiveHandlerError, error
118
132
  end
119
133
  output_files[key] = files.map { |f| File.expand_path(f) }
120
134
  end
@@ -122,19 +136,18 @@ module Biopsy
122
136
  # run all objectives for output
123
137
  results = {}
124
138
  @objectives.each_pair do |name, objective|
125
- results[name] = self.run_objective(objective, name, raw_output, output_files, threads)
139
+ results[name] = self.run_objective(objective, name, raw_output,
140
+ output_files, threads)
126
141
  end
127
142
 
128
143
  if allresults
129
- return {:results => results,
130
- :reduced => self.dimension_reduce(results)}
144
+ return { :results => results,
145
+ :reduced => self.dimension_reduce(results) }
131
146
  else
132
- results.each_pair do |key, value|
147
+ results.each_value do |value|
133
148
  return value.kind_of?(Hash) ? value[:result] : value
134
149
  end
135
150
  end
136
151
  end
137
-
138
152
  end
139
-
140
153
  end
@@ -18,7 +18,7 @@ require 'logger'
18
18
 
19
19
  module Biopsy
20
20
  # options - is a hash of two hashes, :settings and :parameters
21
- # :ranges are arrays to be parameter sweeped
21
+ # :ranges are arrays to be parameter sweeped
22
22
  # ---(single values may be present, these are also remain unchanged but are accessible within the parameters hash to the constructor)
23
23
  class ParameterSweeper
24
24
 
@@ -45,7 +45,7 @@ module Biopsy
45
45
  end
46
46
  end
47
47
 
48
- def setup *args
48
+ def setup(*_args)
49
49
  @best = {
50
50
  :parameters => nil,
51
51
  :score => nil
@@ -54,9 +54,11 @@ module Biopsy
54
54
 
55
55
  # return the next parameter set to evaluate
56
56
  def run_one_iteration(parameters, score)
57
- @current = {:parameters => parameters, :score => score}
57
+ @current = { :parameters => parameters, :score => score }
58
58
  self.update_best?
59
- @combinations.pop rescue nil
59
+ @combinations.pop
60
+ rescue
61
+ nil
60
62
  end
61
63
 
62
64
  def update_best?
@@ -68,7 +70,7 @@ module Biopsy
68
70
  # generate all the parameter combinations to be applied
69
71
  def generate_combinations(index, opts)
70
72
  if index == @ranges.length
71
- @combinations << opts.clone
73
+ @combinations << opts.clone
72
74
  return
73
75
  end
74
76
  # recurse
@@ -88,15 +90,15 @@ module Biopsy
88
90
  end
89
91
 
90
92
  def select_starting_point
91
- return @combinations.pop
93
+ @combinations.pop
92
94
  end
93
95
 
94
96
  def random_start_point
95
- return @combinations.pop
97
+ @combinations.pop
96
98
  end
97
99
 
98
100
  def finished?
99
- return @combinations.empty?
101
+ @combinations.empty?
100
102
  end
101
103
 
102
104
  # True if this algorithm chooses its own starting point
@@ -30,7 +30,7 @@ module Biopsy
30
30
  @range = range
31
31
  @sd_increment_proportion = sd_increment_proportion
32
32
  self.generate_distribution
33
- rescue
33
+ rescue
34
34
  raise "generation of distribution with mean: #{@mean}, sd: #{@sd} failed."
35
35
  end
36
36
 
@@ -45,7 +45,7 @@ module Biopsy
45
45
  end
46
46
 
47
47
  # loosen the distribution by increasing the sd
48
- # and renerating
48
+ # and regenerating
49
49
  def loosen(factor=1)
50
50
  @sd += @sd_increment_proportion * factor * @range.size
51
51
  self.limit_sd
@@ -159,8 +159,8 @@ module Biopsy
159
159
  class TabuSearch #< OptmisationAlgorithm
160
160
 
161
161
  attr_reader :current, :best, :hood_no
162
- attr_accessor :max_hood_size, :sd_increment_proportion, :starting_sd_divisor, :backtrack_cutoff
163
- attr_accessor :jump_cutoff
162
+ attr_accessor :max_hood_size, :sd_increment_proportion
163
+ attr_accessor :starting_sd_divisor, :backtrack_cutoff, :jump_cutoff
164
164
 
165
165
  Thread = Struct.new(:best, :tabu, :distributions,
166
166
  :standard_deviations, :recent_scores,
data/lib/biopsy/target.rb CHANGED
@@ -5,6 +5,9 @@ module Biopsy
5
5
  class TargetLoadError < Exception
6
6
  end
7
7
 
8
+ class TypeLoadError < Exception
9
+ end
10
+
8
11
  class Target
9
12
  require 'yaml'
10
13
  require 'set'
@@ -104,12 +107,25 @@ module Biopsy
104
107
  # optimise this parameter
105
108
  if data[:values]
106
109
  # definition has provided an array of values
107
- raise TargetLoadError.new("'values' for parameter #{param} is not an array") unless data[:values].is_a? Array
110
+ if !data[:values].is_a? Array
111
+ raise TargetLoadError.new("'values' for parameter #{param} is not an array")
112
+ end
113
+ if data[:type] == 'integer'
114
+ data[:values].each do |v|
115
+ raise TypeLoadError.new("'values' for parameter #{param} expected integer") unless v.is_a? Integer
116
+ end
117
+ elsif data[:type] == 'string'
118
+ data[:values].each do |v|
119
+ raise TypeLoadError.new("'values' for parameter #{param} expected string") unless v.is_a? String
120
+ end
121
+ end
108
122
  @parameters[param] = data[:values]
109
123
  else
110
124
  # definition has specified a range
111
125
  min, max, step = data[:min], data[:max], data[:step]
112
- raise TargetLoadError.new("min and max must be set for parameter #{param}") unless min && max
126
+ unless min && max
127
+ raise TargetLoadError.new("min and max must be set for parameter #{param}")
128
+ end
113
129
  range = (min..max)
114
130
  range = range.step(step) if step
115
131
  @parameters[param] = range.to_a
@@ -128,10 +144,10 @@ module Biopsy
128
144
 
129
145
  # pass calls to missing methods to the constructor iff
130
146
  # the constructor's class directly defines that method
131
- def method_missing(meth, *args, &block)
147
+ def method_missing(method, *args, &block)
132
148
  const_methods = @constructor.class.instance_methods(false)
133
- if const_methods.include? meth
134
- @constructor
149
+ if const_methods.include? method
150
+ return @constructor.send(method, *args, &block)
135
151
  else
136
152
  super
137
153
  end
@@ -139,9 +155,9 @@ module Biopsy
139
155
 
140
156
  # accurately report ability to respond to methods passed
141
157
  # to constructor
142
- def method_missing(meth, *args, &block)
158
+ def respond_to?(method, *args, &block)
143
159
  const_methods = @constructor.class.instance_methods(false)
144
- if const_methods.include? meth
160
+ if const_methods.include? method
145
161
  true
146
162
  else
147
163
  super
@@ -1,10 +1,12 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Biopsy
4
+
5
+
4
6
  module VERSION
5
7
  MAJOR = 0
6
- MINOR = 1
7
- PATCH = 9
8
+ MINOR = 2
9
+ PATCH = 0
8
10
 
9
11
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
12
  end
@@ -0,0 +1,3 @@
1
+ ---
2
+ :objectives_dir: ./objectives
3
+ :wrongkey: this_should_cause_error
data/test/helper.rb CHANGED
@@ -106,7 +106,7 @@ class TargetTest
106
106
  end
107
107
 
108
108
  def fake_method
109
- true
109
+ :fake_method_success
110
110
  end
111
111
 
112
112
  end
@@ -153,6 +153,24 @@ end
153
153
  self.string_dump objective, @objective_path
154
154
  end
155
155
 
156
+ def create_invalid_objective
157
+ objective = %Q{
158
+ class TestObjective2 < Biopsy::ObjectiveFunction
159
+
160
+ require 'yaml'
161
+
162
+ def initialize
163
+ @optimum = 0
164
+ @max = 0
165
+ @weighting = 1
166
+ end
167
+
168
+ end
169
+ }
170
+ @objective_path = File.join(@objective_dir, 'test_objective2.rb')
171
+ self.string_dump objective, @objective_path
172
+ end
173
+
156
174
  # Dump +:object+ as YAML to +:file+
157
175
  def yaml_dump object, file
158
176
  self.string_dump object.to_yaml, file
@@ -24,25 +24,27 @@ class TestExperiment < Test::Unit::TestCase
24
24
  @h.cleanup
25
25
  end
26
26
 
27
- should "fail to init when passed a non existent target" do
27
+ should 'fail to init when passed a non existent target' do
28
28
  assert_raise Biopsy::TargetLoadError do
29
29
  Biopsy::Experiment.new('fake_target')
30
30
  end
31
31
  end
32
32
 
33
- should "be able to select a valid point from the parameter space" do
33
+ should 'be able to select a valid point from the parameter space' do
34
34
  e = Biopsy::Experiment.new('target_test')
35
35
  start_point = e.random_start_point
36
36
  start_point.each_pair do |param, value|
37
- assert @target.parameters[param].include?(value), "#{value} not in #{@target.parameters[param]}"
37
+ assert @target.parameters[param].include?(value),
38
+ "#{value} not in #{@target.parameters[param]}"
38
39
  end
39
40
  end
40
41
 
41
- should "be able to select a starting point" do
42
+ should 'be able to select a starting point' do
42
43
  e = Biopsy::Experiment.new('target_test')
43
44
  start_point = e.start
44
45
  start_point.each_pair do |param, value|
45
- assert @target.parameters[param].include?(value), "#{value} not in #{@target.parameters[param]}"
46
+ assert @target.parameters[param].include?(value),
47
+ "#{value} not in #{@target.parameters[param]}"
46
48
  end
47
49
  end
48
50
 
@@ -52,12 +54,12 @@ class TestExperiment < Test::Unit::TestCase
52
54
  assert_equal s, e.start
53
55
  end
54
56
 
55
- should "automatically select an optimiser if none is specified" do
57
+ should 'automatically select an optimiser if none is specified' do
56
58
  e = Biopsy::Experiment.new('target_test')
57
59
  assert e.algorithm.kind_of? Biopsy::TabuSearch
58
60
  end
59
61
 
60
- should "return an optimal set of parameters and score when run" do
62
+ should 'return an optimal set of parameters and score when run' do
61
63
  Dir.chdir @h.tmp_dir do
62
64
  e = Biopsy::Experiment.new('target_test', verbosity: :silent)
63
65
  known_best = -4
@@ -66,7 +68,11 @@ class TestExperiment < Test::Unit::TestCase
66
68
  end
67
69
  end
68
70
 
69
- should "run really quickly when starting from the optimal parameters" do
71
+ should 'always finish running an experiment' do
72
+ assert_equal false, true, 'not yet implemented'
73
+ end
74
+
75
+ should 'run really quickly when starting from the optimal parameters' do
70
76
  Dir.chdir @h.tmp_dir do
71
77
  s = {:a => 4, :b => 4, :c => 4}
72
78
  e = Biopsy::Experiment.new('target_test', start: s, verbosity: :silent)
@@ -76,14 +82,13 @@ class TestExperiment < Test::Unit::TestCase
76
82
  end
77
83
  end
78
84
 
79
- should "run using the parameter sweeper (with limit)" do
85
+ should 'run using the parameter sweeper (with limit)' do
80
86
  Dir.chdir @h.tmp_dir do
81
87
  p = Biopsy::ParameterSweeper.new(@target.parameters, limit: 250)
82
88
  e = Biopsy::Experiment.new('target_test', algorithm: p, verbosity: :silent)
83
89
  best_found = e.run[:score]
84
- assert best_found != nil
90
+ assert best_found
85
91
  end
86
92
  end
87
93
  end # Experiment context
88
-
89
- end # TestExperiment
94
+ end # TestExperiment
@@ -61,11 +61,32 @@ class TestObjectiveHandler < Test::Unit::TestCase
61
61
  f.puts values.to_yaml
62
62
  end
63
63
  Dir.chdir(@h.tmp_dir) do
64
- result = oh.run_for_output(nil, {:onlyfile => file})
64
+ result = oh.run_for_output(nil, 1, nil)
65
65
  assert_equal 0, result
66
66
  end
67
67
  end
68
68
 
69
+ should "run an objective and return all the results" do
70
+ oh = Biopsy::ObjectiveHandler.new @target
71
+ values = {
72
+ :a => 4,
73
+ :b => 4,
74
+ :c => 4
75
+ }
76
+ file = File.expand_path(File.join(@h.tmp_dir, 'output.txt'))
77
+ File.open(file, 'w') do |f|
78
+ f.puts values.to_yaml
79
+ end
80
+ expected = {:results=> {
81
+ "TestObjective"=>{:optimum=>0, :max=>0, :weighting=>1, :result=>-0.0}
82
+ },
83
+ :reduced => 0.0}
84
+ Dir.chdir(@h.tmp_dir) do
85
+ result = oh.run_for_output(nil, 1, 1)
86
+ assert_equal result, expected
87
+ end
88
+ end
89
+
69
90
  should "perform euclidean distance dimension reduction" do
70
91
  oh = Biopsy::ObjectiveHandler.new @target
71
92
  results = {
@@ -91,6 +112,41 @@ class TestObjectiveHandler < Test::Unit::TestCase
91
112
  assert_equal 0.47140452079103173, oh.dimension_reduce(results)
92
113
  end
93
114
 
115
+ should "raise NotImplementedError" do
116
+ @h.create_invalid_objective
117
+ oh = Biopsy::ObjectiveHandler.new @target
118
+ values = {
119
+ :a => 4,
120
+ :b => 4,
121
+ :c => 4
122
+ }
123
+ file = File.expand_path(File.join(@h.tmp_dir, 'output.txt'))
124
+ File.open(file, 'w') do |f|
125
+ f.puts values.to_yaml
126
+ end
127
+ Dir.chdir(@h.tmp_dir) do
128
+ assert_raise NotImplementedError do
129
+ result = oh.run_for_output(nil, 1, nil)
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ should "raise ObjectiveHandlerError" do
136
+ oh = Biopsy::ObjectiveHandler.new @target
137
+ values = {}
138
+ # file = File.expand_path(File.join(@h.tmp_dir, 'output.txt'))
139
+ # File.open(file, 'w') do |f|
140
+ # f.puts values.to_yaml
141
+ # end
142
+ Dir.chdir(@h.tmp_dir) do
143
+ assert_raise Biopsy::ObjectiveHandlerError do
144
+ result = oh.run_for_output(nil, 1, nil)
145
+ end
146
+ end
147
+
148
+ end
149
+
94
150
  end # Experiment context
95
151
 
96
152
  end # TestExperiment
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+
3
+ class TestParameterSweeper < Test::Unit::TestCase
4
+
5
+ context "ParameterSweeper" do
6
+
7
+ setup do
8
+ ranges = {:a => [1,2,3], :b => [1,2,3]}
9
+ @sweep = Biopsy::ParameterSweeper.new(ranges)
10
+ end
11
+
12
+ should "generate a list of combinations" do
13
+ c = @sweep.combinations
14
+ assert_equal c.size, 9
15
+ assert_equal c, [{:a=>1, :b=>1}, {:a=>1, :b=>2}, {:a=>1, :b=>3},
16
+ {:a=>2, :b=>1}, {:a=>2, :b=>2}, {:a=>2, :b=>3},
17
+ {:a=>3, :b=>1}, {:a=>3, :b=>2}, {:a=>3, :b=>3}]
18
+ end
19
+
20
+ end # Experiment context
21
+
22
+ end # TestExperiment
@@ -17,13 +17,19 @@ class TestSettings < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  teardown do
20
- File.delete @config_file if File.exists? @config_file
20
+ File.delete @config_file if File.exist? @config_file
21
21
  end
22
22
 
23
23
  should "load the specified config file" do
24
24
  assert @settings.objectives_dir == @data[:objectives_dir]
25
25
  end
26
26
 
27
+ should "raise an error on loading invalid YAML file" do
28
+ assert_raise(Biopsy::SettingsError) do
29
+ @settings.load(File.expand_path('test/brokenconfig.yml'))
30
+ end
31
+ end
32
+
27
33
  should "complain about malformed config file" do
28
34
  # write non-YAML data to file
29
35
  File.open(@config_file, 'w') do |f|
@@ -38,7 +44,7 @@ class TestSettings < Test::Unit::TestCase
38
44
  @settings.save @config_file
39
45
  @settings.load @config_file
40
46
  @data.each_pair do |key, value|
41
- varname = "@#{key.to_s}".to_sym
47
+ varname = "@#{key}".to_sym
42
48
  assert_equal value, @settings.instance_variable_get(varname)
43
49
  end
44
50
  end
@@ -48,18 +54,19 @@ class TestSettings < Test::Unit::TestCase
48
54
  end
49
55
 
50
56
  should "make loaded settings available as methods" do
51
- assert @settings.objectives_dir == @data[:objectives_dir], 'objectives_dir key not loaded as method'
57
+ assert @settings.objectives_dir == @data[:objectives_dir],
58
+ 'objectives_dir key not loaded as method'
52
59
  end
53
60
 
54
61
  should "produce a YAML string representation" do
55
62
  s = @settings.to_s
56
63
  h = YAML.load(s)
57
64
  h.each_pair do |key, value|
58
- varname = "@#{key.to_s}".to_sym
65
+ varname = "@#{key}".to_sym
59
66
  assert_equal value, @settings.instance_variable_get(varname)
60
67
  end
61
68
  end
62
69
 
63
70
  end # RunHandler context
64
71
 
65
- end # TestRunHandler
72
+ end # TestRunHandler
data/test/test_target.rb CHANGED
@@ -56,6 +56,7 @@ class TestTarget < Test::Unit::TestCase
56
56
 
57
57
  should "be able to store a loaded config file" do
58
58
  config = YAML::load_file(@h.target_path).deep_symbolize
59
+ config[:shortname] = 'tt'
59
60
  @target.store_config config
60
61
  @h.target_data.each_pair do |key, value|
61
62
  if key == :parameters
@@ -65,10 +66,10 @@ class TestTarget < Test::Unit::TestCase
65
66
  r = (spec[:min]..spec[:max])
66
67
  r = spec[:step] ? r.step(spec[:step]) : r
67
68
  parsed[param] = r.to_a
68
- elsif spec[:values]
69
- parsed[param] = spec[:values]
70
- else
71
- assert false, "parameter #{param} with spec #{spec} has no range or values"
69
+ # elsif spec[:values]
70
+ # parsed[param] = spec[:values]
71
+ # else
72
+ # assert false, "parameter #{param} with spec #{spec} has no range or values"
72
73
  end
73
74
  end
74
75
  parsed.each_pair do |param, spec|
@@ -95,10 +96,81 @@ class TestTarget < Test::Unit::TestCase
95
96
  File.delete @target.constructor_path
96
97
  end
97
98
 
98
- should "pass missing method calls to constructor iff it directly defines them" do
99
+ should "raise an exception if values doesn't provide an array" do
100
+ params = {
101
+ :a => {
102
+ :type => 'integer',
103
+ :opt => true,
104
+ :values => 3
105
+ }
106
+ }
107
+ assert_raise Biopsy::TargetLoadError do
108
+ @target.generate_parameters params
109
+ end
110
+ end
111
+
112
+ should "raise an exception for trying to load a string as an integer" do
113
+ params = {
114
+ :a => {
115
+ :type => 'integer',
116
+ :opt => true,
117
+ :values => ["yes","no","maybe"]
118
+ }
119
+ }
120
+ assert_raise Biopsy::TypeLoadError do
121
+ @target.generate_parameters params
122
+ end
123
+ end
124
+
125
+ should "raise an exception for trying to load an integer as a string" do
126
+ params = {
127
+ :b => {
128
+ :type => 'string',
129
+ :opt => true,
130
+ :values => [1,2,3]
131
+ }
132
+ }
133
+ assert_raise Biopsy::TypeLoadError do
134
+ @target.generate_parameters params
135
+ end
136
+ end
137
+
138
+ should "raise an exception of type TargetLoadError" do
139
+ params = {
140
+ :a => {
141
+ :type => 'integer',
142
+ :opt => true
143
+ }
144
+ }
145
+ assert_raise Biopsy::TargetLoadError do
146
+ @target.generate_parameters params
147
+ end
148
+ end
149
+
150
+ should "load array" do
151
+ params = {
152
+ :a => {
153
+ :type => 'string',
154
+ :opt => true,
155
+ :values => ["yes","no","maybe"]
156
+ },
157
+ :b => {
158
+ :type => 'integer',
159
+ :opt => false,
160
+ :values => 0
161
+ }
162
+ }
163
+ @target.generate_parameters params
164
+ assert_equal @target.parameters, {:a => ["yes", "no", "maybe"]}
165
+ assert_equal @target.options, {:b=>{:type=>"integer", :opt=>false, :values=>0}}
166
+ end
167
+
168
+ should "pass missing method calls to constructor iff \
169
+ it directly defines them" do
99
170
  # this method is defined on the constructor in helper.rb
100
171
  assert_send([@target, :fake_method],
101
172
  'valid method not passed to constructor')
173
+ assert_equal @target.fake_method, :fake_method_success
102
174
  assert_raise NoMethodError do
103
175
  @target.totes_fake_method
104
176
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: biopsy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-24 00:00:00.000000000 Z
11
+ date: 2014-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '10.3'
19
+ version: '10.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '10.3'
26
+ version: '10.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: threach
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: turn
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '0.9'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '0.9'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -142,30 +142,32 @@ executables: []
142
142
  extensions: []
143
143
  extra_rdoc_files: []
144
144
  files:
145
- - LICENSE.txt
146
- - README.md
147
145
  - Rakefile
148
146
  - lib/biopsy.rb
149
- - lib/biopsy/base_extensions.rb
150
- - lib/biopsy/experiment.rb
151
- - lib/biopsy/objective_function.rb
147
+ - lib/biopsy/version.rb
152
148
  - lib/biopsy/objective_handler.rb
153
149
  - lib/biopsy/objectives/fastest_optimum.rb
150
+ - lib/biopsy/settings.rb
151
+ - lib/biopsy/optimisers/tabu_search.rb
154
152
  - lib/biopsy/optimisers/genetic_algorithm.rb
155
- - lib/biopsy/optimisers/parameter_sweeper.rb
156
153
  - lib/biopsy/optimisers/spea2.rb
157
- - lib/biopsy/optimisers/tabu_search.rb
158
- - lib/biopsy/settings.rb
154
+ - lib/biopsy/optimisers/parameter_sweeper.rb
155
+ - lib/biopsy/objective_function.rb
159
156
  - lib/biopsy/target.rb
160
- - lib/biopsy/version.rb
161
- - test/helper.rb
162
- - test/test_experiment.rb
163
- - test/test_file.rb
157
+ - lib/biopsy/base_extensions.rb
158
+ - lib/biopsy/experiment.rb
159
+ - test/test_parametersweep.rb
160
+ - test/test_target.rb
164
161
  - test/test_hash.rb
162
+ - test/test_string.rb
163
+ - test/helper.rb
164
+ - test/brokenconfig.yml
165
165
  - test/test_objective_handler.rb
166
+ - test/test_file.rb
166
167
  - test/test_settings.rb
167
- - test/test_string.rb
168
- - test/test_target.rb
168
+ - test/test_experiment.rb
169
+ - README.md
170
+ - LICENSE.txt
169
171
  homepage: https://github.com/Blahah/biopsy
170
172
  licenses: []
171
173
  metadata: {}
@@ -185,9 +187,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
187
  version: '0'
186
188
  requirements: []
187
189
  rubyforge_project:
188
- rubygems_version: 2.2.2
190
+ rubygems_version: 2.1.4
189
191
  signing_key:
190
192
  specification_version: 4
191
193
  summary: framework for optimising any computational pipeline or program
192
194
  test_files: []
193
- has_rdoc: