feldtruby 0.3.14 → 0.3.16
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/feldtruby/array/permutations_and_subsets.rb +11 -0
- data/lib/feldtruby/logger.rb +64 -0
- data/lib/feldtruby/minitest_extensions.rb +8 -0
- data/lib/feldtruby/statistics.rb +42 -5
- data/lib/feldtruby/version.rb +1 -1
- data/test/helper.rb +2 -1
- data/test/test_array_permutations_and_subsets.rb +43 -0
- data/test/test_html_doc_getter.rb +28 -9
- data/test/test_logger.rb +96 -0
- data/test/test_statistics.rb +13 -1
- metadata +8 -2
@@ -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
|
data/lib/feldtruby/statistics.rb
CHANGED
@@ -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
|
114
|
-
# to a String that can be used in R code/scripts to
|
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
|
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(#{
|
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
|
|
data/lib/feldtruby/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
data/test/test_logger.rb
ADDED
@@ -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
|
data/test/test_statistics.rb
CHANGED
@@ -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
|
-
|
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.
|
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-
|
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
|