biopsy 0.1.9 → 0.2.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.
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: