feldtruby 0.3.14 → 0.3.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def all_pairs
3
+
4
+ return [] if length < 2
5
+
6
+ x, *rest = self
7
+
8
+ rest.map {|e| [x, e]} + rest.all_pairs
9
+
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ require 'stringio'
2
+
3
+ module FeldtRuby
4
+
5
+ class Logger
6
+ def initialize(io = STDOUT)
7
+
8
+ @io = io
9
+
10
+ # We save a unique array of events for each type.
11
+ @events = Hash.new {|h,k| h[k] = Array.new}
12
+
13
+ end
14
+
15
+ # Return the number of events of type _eventType_.
16
+ def num_events eventType = nil
17
+ @events[eventType].length
18
+ end
19
+
20
+ Event = Struct.new(:description, :time_stamp)
21
+
22
+ # Count an event of type _eventType_.
23
+ def log_event eventType = nil, description = ""
24
+ @events[eventType] << Event.new(description, Time.now)
25
+ end
26
+
27
+ # Return all the events, i.e. descriptions and time stamp, for a given _eventType_.
28
+ def events(eventType = nil)
29
+ @events[eventType]
30
+ end
31
+
32
+ # Return all the event descriptions for a given _eventType_.
33
+ def event_descriptions(eventType = nil)
34
+ @events[eventType].map {|e| e.description}
35
+ end
36
+
37
+ # Log an event described by a string _str_ optionally with an event type
38
+ # _eventType_.
39
+ def log str, eventType = nil
40
+
41
+ description = log_entry_description(str, eventType)
42
+
43
+ log_event eventType, description
44
+
45
+ io_puts description
46
+
47
+ end
48
+
49
+ # Puts the given _str_ on the io stream.
50
+ def io_puts str
51
+ @io.puts str
52
+ end
53
+
54
+ # Map a string and event type to a log string.
55
+ def log_entry_description str, eventType = nil
56
+
57
+ event_tag = eventType ? "{#{eventType.to_s}}: " : ""
58
+
59
+ event_tag + str
60
+
61
+ end
62
+ end
63
+
64
+ end
@@ -20,6 +20,14 @@ module MiniTest::Assertions
20
20
  end
21
21
  end
22
22
 
23
+ NumTestRepetitions = 50
24
+
25
+ def repeatedly_it(message, &testcode)
26
+ NumTestRepetitions.times do |i|
27
+ it("#{i}: " + message, &testcode)
28
+ end
29
+ end
30
+
23
31
  module MiniTest::Expectations
24
32
  infect_an_assertion :assert_similar_proportions, :must_have_similar_proportions
25
33
  infect_an_assertion :assert_falsey, :must_be_falsey
@@ -110,8 +110,9 @@ class RCommunicator
110
110
  end
111
111
  end
112
112
 
113
- # Convert a Ruby object of one of the types String, Array, Integer or Float
114
- # to a String that can be used in R code/scripts to represent the object.
113
+ # Convert a Ruby object of one of the types String, Symbol, Array, Integer
114
+ # or Float to a String that can be used in R code/scripts to
115
+ # represent the object.
115
116
  def ruby_object_to_R_string(o)
116
117
 
117
118
  case o
@@ -119,6 +120,9 @@ class RCommunicator
119
120
  when String
120
121
  return o.inspect
121
122
 
123
+ when Symbol
124
+ return o.to_s
125
+
122
126
  when Array
123
127
  elems = o.map {|e| ruby_object_to_R_string(e)}.join(", ")
124
128
  return "c(#{elems})"
@@ -164,6 +168,10 @@ module Statistics
164
168
  res.p_value
165
169
  end
166
170
 
171
+ def correlation(ary1, ary2)
172
+ RC.call("cor", ary1, ary2)
173
+ end
174
+
167
175
  class DiffusionKDE
168
176
  attr_reader :densities, :mesh
169
177
 
@@ -246,9 +254,38 @@ module FeldtRuby::Statistics::Plotting
246
254
 
247
255
  end
248
256
 
249
- def hexbin_heatmap(csvFilePath, xlabel, ylabel, title = "heatmap", bins = 20)
257
+ def filled_contour(csvFilePath, xlabel, ylabel, title = "filled.contour")
258
+ include_library "MASS"
259
+ #include_library "ggplot2"
260
+
261
+ script = <<-EOS
262
+ data <- read.csv(#{csvFilePath.inspect})
263
+ k <- with(data, MASS::kde2d(#{xlabel}, #{ylabel}))
264
+ f <- filled.contour(k, color=topo.colors,
265
+ plot.title=title(main = _title_),
266
+ xlab=_xlabel_, ylab=_ylabel_)
267
+ f
268
+ EOS
269
+
270
+ subst_eval script, {:title => title,
271
+ :xlabel => xlabel.to_s, :ylabel => ylabel.to_s}
272
+
273
+ end
274
+
275
+ def smooth_scatter_plot(csvFilePath, xlabel, ylabel, title = "smoothscatter")
276
+ include_library "graphics"
277
+
278
+ script = <<-EOS
279
+ f <- ggplot(data, aes(#{xlabel}, #{ylabel})) +
280
+ geom_point() + geom_smooth( method="loess", se = FALSE )
281
+ EOS
282
+
283
+ plot_2dims(csvFilePath, script, xlabel.to_s, ylabel.to_s, title)
284
+ end
285
+
286
+ def hexbin_heatmap(csvFilePath, xlabel, ylabel, title = "heatmap", bins = 50)
250
287
  plot_2dims(csvFilePath,
251
- "f <- ggplot(data, aes(#{ylabel}, #{ylabel})) + geom_hex( bins = #{bins} )",
288
+ "f <- ggplot(data, aes(#{xlabel}, #{ylabel})) + geom_hex( bins = #{bins} )",
252
289
  xlabel, ylabel, title)
253
290
  end
254
291
 
@@ -260,7 +297,7 @@ module FeldtRuby::Statistics::Plotting
260
297
  f <- f + stat_smooth()
261
298
  EOS
262
299
 
263
- plot_2dims(csvFilePath, script, xlabel, ylabel, title)
300
+ plot_2dims(csvFilePath, script, xlabel.to_s, ylabel.to_s, title)
264
301
 
265
302
  end
266
303
 
@@ -1,3 +1,3 @@
1
1
  module FeldtRuby
2
- VERSION = "0.3.14"
2
+ VERSION = "0.3.16"
3
3
  end
data/test/helper.rb CHANGED
@@ -4,4 +4,5 @@ require 'minitest/spec'
4
4
 
5
5
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
6
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'feldtruby'
7
+ require 'feldtruby'
8
+ require 'feldtruby/minitest_extensions'
@@ -0,0 +1,43 @@
1
+ require 'feldtruby/array/permutations_and_subsets'
2
+
3
+ describe "all pairs of elements from an array" do
4
+
5
+ it "cannot return any pairs if there are fewer than 2 elements" do
6
+
7
+ [].all_pairs.must_equal []
8
+ [1].all_pairs.must_equal []
9
+ [:a].all_pairs.must_equal []
10
+
11
+ end
12
+
13
+ it "returns the only pair if 2 elements" do
14
+
15
+ [1, 2].all_pairs.must_equal [[1, 2]]
16
+ [1, "a"].all_pairs.must_equal [[1, "a"]]
17
+
18
+ end
19
+
20
+ it "returns the right pairs when 3 elements" do
21
+
22
+ [1, 2, 3].all_pairs.sort.must_equal [[1, 2], [1, 3], [2, 3]].sort
23
+
24
+ end
25
+
26
+ def invariant_all_original_elements_are_at_least_in_one_pair(ary)
27
+
28
+ ary.all_pairs.flatten.uniq.sort.must_equal ary.uniq.sort
29
+
30
+ end
31
+
32
+ repeatedly_it "returns the right number of pairs when > 3 elements" do
33
+
34
+ ary = Array.new(4 + rand(10)).map {rand(1000)}
35
+
36
+ invariant_all_original_elements_are_at_least_in_one_pair ary
37
+
38
+ num_pairs = ary.all_pairs
39
+ n = ary.length
40
+
41
+ end
42
+
43
+ end
@@ -1,16 +1,35 @@
1
1
  require 'minitest/spec'
2
2
  require 'feldtruby/net/html_doc_getter'
3
3
 
4
- describe "HtmlDocGetter" do
5
- it "Can get the html page as a string" do
6
- h = FeldtRuby::HtmlDocGetter.new
7
- s = h.get("http://www.google.com")
8
- s.must_be_instance_of String
4
+ # Skip these network-dependent tests if we have no network connection.
5
+ def has_network_connection?
6
+ begin
7
+ open("http://www.google.se")
8
+ return true
9
+ rescue Exception => e
10
+ return false
9
11
  end
12
+ end
10
13
 
11
- it "Can get the html page as a Nokogiri doc" do
12
- h = FeldtRuby::HtmlDocGetter.new
13
- d = h.get_html_doc("http://www.google.com")
14
- d.must_be_instance_of Nokogiri::HTML::Document
14
+ def quicker_has_network_connection?
15
+ reply = `ping -o google.se`
16
+ reply != "" # Is empty if no connection since error is printed on STDERR
17
+ end
18
+
19
+ if quicker_has_network_connection?
20
+
21
+ describe "HtmlDocGetter" do
22
+ it "Can get the html page as a string" do
23
+ h = FeldtRuby::HtmlDocGetter.new
24
+ s = h.get("http://www.google.com")
25
+ s.must_be_instance_of String
26
+ end
27
+
28
+ it "Can get the html page as a Nokogiri doc" do
29
+ h = FeldtRuby::HtmlDocGetter.new
30
+ d = h.get_html_doc("http://www.google.com")
31
+ d.must_be_instance_of Nokogiri::HTML::Document
32
+ end
15
33
  end
34
+
16
35
  end
@@ -0,0 +1,96 @@
1
+ require 'feldtruby/logger'
2
+
3
+ describe 'Logger' do
4
+
5
+ before do
6
+ @sio = StringIO.new
7
+ @l = FeldtRuby::Logger.new @sio
8
+ end
9
+
10
+ it 'has a event count of 0 when no events has been logged' do
11
+
12
+ @l.num_events.must_equal 0
13
+
14
+ end
15
+
16
+ it 'increases default event count when default events are logged' do
17
+
18
+ @l.log "1"
19
+ @l.num_events.must_equal 1
20
+
21
+ @l.log "2"
22
+ @l.num_events.must_equal 2
23
+
24
+ end
25
+
26
+ it 'can log default events (described in strings)' do
27
+
28
+ @l.log "event 1"
29
+ @sio.string.must_equal "event 1\n"
30
+ @l.num_events.must_equal 1
31
+
32
+ @l.log "event 2"
33
+ @sio.string.must_equal "event 1\nevent 2\n"
34
+ @l.num_events.must_equal 2
35
+
36
+ end
37
+
38
+ it 'can log events of a given type' do
39
+
40
+ @l.log "1", :increase
41
+ @sio.string.must_equal "{increase}: 1\n"
42
+ @l.num_events.must_equal 0
43
+ @l.num_events(:increase).must_equal 1
44
+
45
+ @l.log "2", :increase
46
+ @sio.string.must_equal "{increase}: 1\n{increase}: 2\n"
47
+ @l.num_events.must_equal 0
48
+ @l.num_events(:increase).must_equal 2
49
+
50
+ end
51
+
52
+ it 'can return old default events' do
53
+
54
+ @l.log "event 1"
55
+ @l.event_descriptions.must_equal ["event 1"]
56
+
57
+ @l.log "event 2"
58
+ @l.event_descriptions.must_equal ["event 1", "event 2"]
59
+
60
+ end
61
+
62
+ it 'can return old events of given type' do
63
+
64
+ @l.log "1", :increase
65
+ @l.log "2", :increase
66
+ @l.log "0.4", :alpha
67
+ @l.log "1", :increase
68
+
69
+ @l.event_descriptions(:increase).must_equal ["{increase}: 1", "{increase}: 2", "{increase}: 1"]
70
+
71
+ @l.event_descriptions(:alpha).must_equal ["{alpha}: 0.4"]
72
+
73
+ @l.event_descriptions(:beta).must_equal []
74
+
75
+ end
76
+
77
+ it 'time stamps each log entry' do
78
+
79
+ @l.log "1", :a
80
+ @l.log "2", :b
81
+ @l.log "2", :a
82
+
83
+ time_stamps_a = @l.events(:a).map {|e| e.time_stamp}
84
+ time_stamps_b = @l.events(:b).map {|e| e.time_stamp}
85
+
86
+ time_stamps_a[0].must_be_instance_of Time
87
+ time_stamps_a[1].must_be_instance_of Time
88
+ time_stamps_b[0].must_be_instance_of Time
89
+
90
+ time_stamps_a[0].must_be :<, time_stamps_a[1]
91
+ time_stamps_a[0].must_be :<, time_stamps_b[0]
92
+ time_stamps_b[0].must_be :<, time_stamps_a[1]
93
+
94
+ end
95
+
96
+ end
@@ -82,6 +82,18 @@ describe "Statistics" do
82
82
  kde.densities[3].must_be_close_to 0.2728
83
83
  end
84
84
  end
85
+
86
+ describe "correlation between Ruby arrays" do
87
+
88
+ it "works for a simple example from the R doc for cor" do
89
+ correlation( (1..10).to_a, (2..11).to_a ).must_equal 1
90
+ end
91
+
92
+ it "works for the inverse of the simple example from the R doc for cor" do
93
+ correlation( (1..10).to_a, (-11..-2).to_a.reverse ).must_equal -1
94
+ end
95
+
96
+ end
85
97
  end
86
98
 
87
99
  require 'feldtruby/minitest_extensions'
@@ -154,7 +166,7 @@ describe "Plotting" do
154
166
 
155
167
  File.exist?(out).must_equal true
156
168
 
157
- #File.delete out
169
+ File.delete out
158
170
 
159
171
  end
160
172
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feldtruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.14
4
+ version: 0.3.16
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-11 00:00:00.000000000 Z
12
+ date: 2013-03-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rinruby
@@ -79,9 +79,11 @@ files:
79
79
  - lib/feldtruby/array.rb
80
80
  - lib/feldtruby/array/basic_stats.rb
81
81
  - lib/feldtruby/array/count_by.rb
82
+ - lib/feldtruby/array/permutations_and_subsets.rb
82
83
  - lib/feldtruby/file/file_change_watcher.rb
83
84
  - lib/feldtruby/file/tempfile.rb
84
85
  - lib/feldtruby/float.rb
86
+ - lib/feldtruby/logger.rb
85
87
  - lib/feldtruby/math/rand.rb
86
88
  - lib/feldtruby/minitest_extensions.rb
87
89
  - lib/feldtruby/net/html_doc_getter.rb
@@ -115,11 +117,13 @@ files:
115
117
  - test/test_array.rb
116
118
  - test/test_array_basic_stats.rb
117
119
  - test/test_array_count_by.rb
120
+ - test/test_array_permutations_and_subsets.rb
118
121
  - test/test_clustering.rb
119
122
  - test/test_euclidean_distance.rb
120
123
  - test/test_fastmap.rb
121
124
  - test/test_float.rb
122
125
  - test/test_html_doc_getter.rb
126
+ - test/test_logger.rb
123
127
  - test/test_normalization.rb
124
128
  - test/test_optimize.rb
125
129
  - test/test_optimize_differential_evolution.rb
@@ -165,11 +169,13 @@ test_files:
165
169
  - test/test_array.rb
166
170
  - test/test_array_basic_stats.rb
167
171
  - test/test_array_count_by.rb
172
+ - test/test_array_permutations_and_subsets.rb
168
173
  - test/test_clustering.rb
169
174
  - test/test_euclidean_distance.rb
170
175
  - test/test_fastmap.rb
171
176
  - test/test_float.rb
172
177
  - test/test_html_doc_getter.rb
178
+ - test/test_logger.rb
173
179
  - test/test_normalization.rb
174
180
  - test/test_optimize.rb
175
181
  - test/test_optimize_differential_evolution.rb