geoptima 0.0.8 → 0.0.9

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.
data/bin/csv_chart CHANGED
@@ -5,15 +5,22 @@ $: << 'lib'
5
5
  $: << '../lib'
6
6
 
7
7
  require 'geoptima/chart'
8
+ require 'geoptima/version'
8
9
  require 'geoptima/options'
9
10
  require 'fileutils'
10
11
 
12
+ Geoptima::assert_version("0.0.9")
13
+
11
14
  $export_dir = '.'
15
+ $diversity = 40.0
12
16
 
13
17
  $files = Geoptima::Options.process_args do |option|
14
18
  option.m {$merge_all = true}
19
+ option.a {$create_all = true}
15
20
  option.D {$export_dir = ARGV.shift}
16
21
  option.N {$merged_name = ARGV.shift}
22
+ option.S {$specfile = ARGV.shift}
23
+ option.P {$diversity = ARGV.shift.to_f}
17
24
  end
18
25
 
19
26
  FileUtils.mkdir_p $export_dir
@@ -21,12 +28,15 @@ FileUtils.mkdir_p $export_dir
21
28
  $help = true unless($files.length>0)
22
29
  if $help
23
30
  puts <<EOHELP
24
- Usage: csv_chart <-dhm> <-N name> <-D dir> files...
31
+ Usage: csv_chart <-dham> <-S specfile> <-N name> <-D dir> files...
25
32
  -d debug mode #{cw $debug}
26
33
  -h print this help #{cw $help}
34
+ -a automatically create charts for all properties #{cw $create_all}
27
35
  -m merge all files into single stats #{cw $merge_all}
28
36
  -N use specified name for merged dataset: #{$merged_name}
29
37
  -D export charts to specified directory: #{$export_dir}
38
+ -S use chart specification in specified file: #{$specfile}
39
+ -P diversity threshold in percentage for automatic reports: #{$diversity}
30
40
  Files to import: #{$files.join(', ')}
31
41
  EOHELP
32
42
  exit
@@ -42,8 +52,16 @@ class Stats
42
52
  @data = fields.map{|h| []}
43
53
  @numerical = fields.map{|h| true}
44
54
  end
55
+ def add_header(h)
56
+ @headers << h
57
+ @stats << {}
58
+ @data << []
59
+ @numerical << true
60
+ @headers.length - 1
61
+ end
45
62
  def add(field,index)
46
- if field =~ /\w/
63
+ puts "\tAdding field '#{field}' at index #{index}" if($debug)
64
+ if field && field =~ /\w/
47
65
  @numerical[index] &&= is_number?(field)
48
66
  puts "\tField[#{index}]: #{field}" if($debug)
49
67
  stats = @stats[index]
@@ -69,7 +87,7 @@ class Stats
69
87
  100.0 * @stats[index].length.to_f / @data[index].length.to_f
70
88
  end
71
89
  def diverse?(index)
72
- @stats[index].length>500 || diversity(index) > 40.0
90
+ @stats[index].length>500 || diversity(index) > $diversity
73
91
  end
74
92
  def numerical?(index)
75
93
  @numerical[index]
@@ -78,6 +96,139 @@ end
78
96
 
79
97
  $stats = {}
80
98
 
99
+ module Geoptima
100
+ class StatSpec
101
+ attr_reader :header, :index, :indices, :fields, :options, :proc
102
+ def initialize(header,*fields,&block)
103
+ @header = header
104
+ @fields = fields
105
+ @proc = block
106
+ if @fields[-1].is_a?(Hash)
107
+ @options = @fields.pop
108
+ else
109
+ @options = {}
110
+ end
111
+ puts "Created StatSpec: #{self}"
112
+ end
113
+ def mk_range(val)
114
+ if val =~ /\w/
115
+ div = options[:div].to_i
116
+ div = 1 if(div<1)
117
+ min = val.to_i/div * div
118
+ "#{min}..#{min+div}"
119
+ else
120
+ val
121
+ end
122
+ end
123
+ def map(values)
124
+ if @indices
125
+ puts "StatSpec[#{self}]: #{options.inspect}" if($debug)
126
+ vals = @indices.map{|i| values[i]}
127
+ if options[:div]
128
+ vals.map!{|v| mk_range(v)}
129
+ end
130
+ puts "StatSpec[#{self}]: #{vals.inspect}" if($debug)
131
+ val = proc.call(*vals)
132
+ puts "StatSpec[#{self}]: #{vals.inspect} --> #{val.inspect}" if($debug)
133
+ val
134
+ end
135
+ end
136
+ def prepare_indices(stats)
137
+ if stats.headers.index(header)
138
+ puts "Header '#{header}' already exists, cannot create #{self}"
139
+ else
140
+ @index = stats.add_header(header)
141
+ @indices = @fields.map{|h| stats.headers.index(h) || stats.headers.index(h.downcase) }
142
+ puts "#{self}: Header[#{@index}], Indices[#{@indices.join(',')}]" if($debug)
143
+ if @indices.compact.length < @fields.length
144
+ puts "Unable to find some headers for #{self}, ignoring stats"
145
+ @indices = nil
146
+ end
147
+ end
148
+ end
149
+ def to_s
150
+ "#{header}[#{index}]<-#{fields.inspect}(#{indices && indices.join(',')})"
151
+ end
152
+ end
153
+ class ChartSpec
154
+ attr_reader :chart_type, :header, :options
155
+ def initialize(chart_type,header,options={})
156
+ @header = header
157
+ @chart_type = chart_type
158
+ @options = options
159
+ end
160
+ def process(stats)
161
+ puts "Charting #{header} using stats.headers: #{stats.headers}"
162
+ index = stats.headers.index(header)
163
+ index ||= stats.headers.index(header.downcase)
164
+ unless index
165
+ puts "Cannot find statistics for '#{header}' - ignoring chart"
166
+ return
167
+ end
168
+ puts "Charting #{header} at index #{index} and options #{options.inspect}"
169
+ puts "Charting #{header} with diversity #{stats.diversity(index)}"
170
+ hist = stats.stats[index]
171
+ title = options[:title]
172
+ if options[:top]
173
+ keys = hist.keys.sort{|a,b| hist[b] <=> hist[a]}[0..(options[:top].to_i)]
174
+ title ||= "#{header} Top #{options[:top]}"
175
+ else
176
+ keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
177
+ end
178
+ values = keys.map{|k| hist[k]}
179
+ title ||= "#{header} Distribution"
180
+ options.merge!( :title => title, :width => 1024 )
181
+ legend = $merge_all ? "ALL" : stats.name
182
+ g = Geoptima::Chart.send "draw_#{chart_type}_chart", stats.name, keys, values, options
183
+ g.write("#{$export_dir}/Chart_#{stats.name}_#{header}_distribution.png")
184
+ end
185
+ def to_s
186
+ "#{chart_type.upcase}-#{header}"
187
+ end
188
+ end
189
+ class StatsSpecs
190
+ attr_reader :chart_specs, :stat_specs
191
+ def initialize(specfile)
192
+ @chart_specs = []
193
+ @stat_specs = []
194
+ instance_eval(File.open(specfile).read)
195
+ end
196
+ def category_chart(header,options={})
197
+ chart(:category, header, options)
198
+ end
199
+ def histogram_chart(header,options={})
200
+ chart(:histogram, header, options)
201
+ end
202
+ def line_chart(header,options={})
203
+ chart(:line, header, options)
204
+ end
205
+ def chart(chart_type,header,options={})
206
+ @chart_specs << ChartSpec.new(chart_type,header,options)
207
+ end
208
+ def stats(header,*fields,&block)
209
+ @stat_specs << StatSpec.new(header,*fields,&block)
210
+ end
211
+ def add_stats(stats)
212
+ stat_specs.each do |stat_spec|
213
+ stat_spec.prepare_indices(stats)
214
+ end
215
+ end
216
+ def add_fields(stats,fields)
217
+ $specs.stat_specs.each do |stat_spec|
218
+ stats.add(
219
+ stat_spec.map(fields),
220
+ stat_spec.index
221
+ )
222
+ end
223
+ end
224
+ def to_s
225
+ "Charts[#{chart_specs.length}]: #{@chart_specs.join(', ')}"
226
+ end
227
+ end
228
+ end
229
+
230
+ $specfile && $specs = Geoptima::StatsSpecs.new($specfile)
231
+
81
232
  $files.each do |file|
82
233
  lines = 0
83
234
  filename = File.basename(file)
@@ -92,15 +243,22 @@ $files.each do |file|
92
243
  fields.each_with_index do |field,index|
93
244
  $stats[file].add(field,index)
94
245
  end
246
+ $specs && $specs.add_fields($stats[file],fields)
95
247
  elsif($merge_all && $stats.length>0)
96
248
  file = $stats.values[0].file
97
249
  else
98
250
  $stats[file] = Stats.new(filename,name,fields)
251
+ $specs && $specs.add_stats($stats[file])
99
252
  end
100
253
  end
101
254
  end
102
255
 
103
256
  $stats.each do |file,stats|
257
+ if $specs
258
+ $specs.chart_specs.each do |chart_spec|
259
+ chart_spec.process(stats)
260
+ end
261
+ else
104
262
  stats.headers.each_with_index do |header,index|
105
263
  puts "Charting #{header} with diversity #{stats.diversity(index)}"
106
264
  case header
@@ -136,7 +294,7 @@ $stats.each do |file,stats|
136
294
 
137
295
  else
138
296
  if stats.diverse?(index)
139
- puts "Ingnoring high diversity field #{header}"
297
+ puts "Ignoring high diversity field #{header}"
140
298
  else
141
299
  puts "Charting field: #{header} with length #{stats.length(index)} and diversity #{stats.diversity(index)}"
142
300
  hist = stats.stats[index]
@@ -156,5 +314,6 @@ $stats.each do |file,stats|
156
314
  end
157
315
  end
158
316
  end
317
+ end
159
318
  end
160
319
 
data/bin/show_geoptima CHANGED
@@ -7,7 +7,7 @@ $: << '../lib'
7
7
  require 'date'
8
8
  require 'geoptima'
9
9
 
10
- Geoptima::assert_version("0.0.8")
10
+ Geoptima::assert_version("0.0.9")
11
11
 
12
12
  $debug=false
13
13
 
@@ -5,15 +5,22 @@ $: << 'lib'
5
5
  $: << '../lib'
6
6
 
7
7
  require 'geoptima/chart'
8
+ require 'geoptima/version'
8
9
  require 'geoptima/options'
9
10
  require 'fileutils'
10
11
 
12
+ Geoptima::assert_version("0.0.9")
13
+
11
14
  $export_dir = '.'
15
+ $diversity = 40.0
12
16
 
13
17
  $files = Geoptima::Options.process_args do |option|
14
18
  option.m {$merge_all = true}
19
+ option.a {$create_all = true}
15
20
  option.D {$export_dir = ARGV.shift}
16
21
  option.N {$merged_name = ARGV.shift}
22
+ option.S {$specfile = ARGV.shift}
23
+ option.P {$diversity = ARGV.shift.to_f}
17
24
  end
18
25
 
19
26
  FileUtils.mkdir_p $export_dir
@@ -21,12 +28,15 @@ FileUtils.mkdir_p $export_dir
21
28
  $help = true unless($files.length>0)
22
29
  if $help
23
30
  puts <<EOHELP
24
- Usage: csv_chart <-dhm> <-N name> <-D dir> files...
31
+ Usage: csv_chart <-dham> <-S specfile> <-N name> <-D dir> files...
25
32
  -d debug mode #{cw $debug}
26
33
  -h print this help #{cw $help}
34
+ -a automatically create charts for all properties #{cw $create_all}
27
35
  -m merge all files into single stats #{cw $merge_all}
28
36
  -N use specified name for merged dataset: #{$merged_name}
29
37
  -D export charts to specified directory: #{$export_dir}
38
+ -S use chart specification in specified file: #{$specfile}
39
+ -P diversity threshold in percentage for automatic reports: #{$diversity}
30
40
  Files to import: #{$files.join(', ')}
31
41
  EOHELP
32
42
  exit
@@ -42,8 +52,16 @@ class Stats
42
52
  @data = fields.map{|h| []}
43
53
  @numerical = fields.map{|h| true}
44
54
  end
55
+ def add_header(h)
56
+ @headers << h
57
+ @stats << {}
58
+ @data << []
59
+ @numerical << true
60
+ @headers.length - 1
61
+ end
45
62
  def add(field,index)
46
- if field =~ /\w/
63
+ puts "\tAdding field '#{field}' at index #{index}" if($debug)
64
+ if field && field =~ /\w/
47
65
  @numerical[index] &&= is_number?(field)
48
66
  puts "\tField[#{index}]: #{field}" if($debug)
49
67
  stats = @stats[index]
@@ -69,7 +87,7 @@ class Stats
69
87
  100.0 * @stats[index].length.to_f / @data[index].length.to_f
70
88
  end
71
89
  def diverse?(index)
72
- @stats[index].length>500 || diversity(index) > 40.0
90
+ @stats[index].length>500 || diversity(index) > $diversity
73
91
  end
74
92
  def numerical?(index)
75
93
  @numerical[index]
@@ -78,6 +96,139 @@ end
78
96
 
79
97
  $stats = {}
80
98
 
99
+ module Geoptima
100
+ class StatSpec
101
+ attr_reader :header, :index, :indices, :fields, :options, :proc
102
+ def initialize(header,*fields,&block)
103
+ @header = header
104
+ @fields = fields
105
+ @proc = block
106
+ if @fields[-1].is_a?(Hash)
107
+ @options = @fields.pop
108
+ else
109
+ @options = {}
110
+ end
111
+ puts "Created StatSpec: #{self}"
112
+ end
113
+ def mk_range(val)
114
+ if val =~ /\w/
115
+ div = options[:div].to_i
116
+ div = 1 if(div<1)
117
+ min = val.to_i/div * div
118
+ "#{min}..#{min+div}"
119
+ else
120
+ val
121
+ end
122
+ end
123
+ def map(values)
124
+ if @indices
125
+ puts "StatSpec[#{self}]: #{options.inspect}" if($debug)
126
+ vals = @indices.map{|i| values[i]}
127
+ if options[:div]
128
+ vals.map!{|v| mk_range(v)}
129
+ end
130
+ puts "StatSpec[#{self}]: #{vals.inspect}" if($debug)
131
+ val = proc.call(*vals)
132
+ puts "StatSpec[#{self}]: #{vals.inspect} --> #{val.inspect}" if($debug)
133
+ val
134
+ end
135
+ end
136
+ def prepare_indices(stats)
137
+ if stats.headers.index(header)
138
+ puts "Header '#{header}' already exists, cannot create #{self}"
139
+ else
140
+ @index = stats.add_header(header)
141
+ @indices = @fields.map{|h| stats.headers.index(h) || stats.headers.index(h.downcase) }
142
+ puts "#{self}: Header[#{@index}], Indices[#{@indices.join(',')}]" if($debug)
143
+ if @indices.compact.length < @fields.length
144
+ puts "Unable to find some headers for #{self}, ignoring stats"
145
+ @indices = nil
146
+ end
147
+ end
148
+ end
149
+ def to_s
150
+ "#{header}[#{index}]<-#{fields.inspect}(#{indices && indices.join(',')})"
151
+ end
152
+ end
153
+ class ChartSpec
154
+ attr_reader :chart_type, :header, :options
155
+ def initialize(chart_type,header,options={})
156
+ @header = header
157
+ @chart_type = chart_type
158
+ @options = options
159
+ end
160
+ def process(stats)
161
+ puts "Charting #{header} using stats.headers: #{stats.headers}"
162
+ index = stats.headers.index(header)
163
+ index ||= stats.headers.index(header.downcase)
164
+ unless index
165
+ puts "Cannot find statistics for '#{header}' - ignoring chart"
166
+ return
167
+ end
168
+ puts "Charting #{header} at index #{index} and options #{options.inspect}"
169
+ puts "Charting #{header} with diversity #{stats.diversity(index)}"
170
+ hist = stats.stats[index]
171
+ title = options[:title]
172
+ if options[:top]
173
+ keys = hist.keys.sort{|a,b| hist[b] <=> hist[a]}[0..(options[:top].to_i)]
174
+ title ||= "#{header} Top #{options[:top]}"
175
+ else
176
+ keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
177
+ end
178
+ values = keys.map{|k| hist[k]}
179
+ title ||= "#{header} Distribution"
180
+ options.merge!( :title => title, :width => 1024 )
181
+ legend = $merge_all ? "ALL" : stats.name
182
+ g = Geoptima::Chart.send "draw_#{chart_type}_chart", stats.name, keys, values, options
183
+ g.write("#{$export_dir}/Chart_#{stats.name}_#{header}_distribution.png")
184
+ end
185
+ def to_s
186
+ "#{chart_type.upcase}-#{header}"
187
+ end
188
+ end
189
+ class StatsSpecs
190
+ attr_reader :chart_specs, :stat_specs
191
+ def initialize(specfile)
192
+ @chart_specs = []
193
+ @stat_specs = []
194
+ instance_eval(File.open(specfile).read)
195
+ end
196
+ def category_chart(header,options={})
197
+ chart(:category, header, options)
198
+ end
199
+ def histogram_chart(header,options={})
200
+ chart(:histogram, header, options)
201
+ end
202
+ def line_chart(header,options={})
203
+ chart(:line, header, options)
204
+ end
205
+ def chart(chart_type,header,options={})
206
+ @chart_specs << ChartSpec.new(chart_type,header,options)
207
+ end
208
+ def stats(header,*fields,&block)
209
+ @stat_specs << StatSpec.new(header,*fields,&block)
210
+ end
211
+ def add_stats(stats)
212
+ stat_specs.each do |stat_spec|
213
+ stat_spec.prepare_indices(stats)
214
+ end
215
+ end
216
+ def add_fields(stats,fields)
217
+ $specs.stat_specs.each do |stat_spec|
218
+ stats.add(
219
+ stat_spec.map(fields),
220
+ stat_spec.index
221
+ )
222
+ end
223
+ end
224
+ def to_s
225
+ "Charts[#{chart_specs.length}]: #{@chart_specs.join(', ')}"
226
+ end
227
+ end
228
+ end
229
+
230
+ $specfile && $specs = Geoptima::StatsSpecs.new($specfile)
231
+
81
232
  $files.each do |file|
82
233
  lines = 0
83
234
  filename = File.basename(file)
@@ -92,15 +243,22 @@ $files.each do |file|
92
243
  fields.each_with_index do |field,index|
93
244
  $stats[file].add(field,index)
94
245
  end
246
+ $specs && $specs.add_fields($stats[file],fields)
95
247
  elsif($merge_all && $stats.length>0)
96
248
  file = $stats.values[0].file
97
249
  else
98
250
  $stats[file] = Stats.new(filename,name,fields)
251
+ $specs && $specs.add_stats($stats[file])
99
252
  end
100
253
  end
101
254
  end
102
255
 
103
256
  $stats.each do |file,stats|
257
+ if $specs
258
+ $specs.chart_specs.each do |chart_spec|
259
+ chart_spec.process(stats)
260
+ end
261
+ else
104
262
  stats.headers.each_with_index do |header,index|
105
263
  puts "Charting #{header} with diversity #{stats.diversity(index)}"
106
264
  case header
@@ -136,7 +294,7 @@ $stats.each do |file,stats|
136
294
 
137
295
  else
138
296
  if stats.diverse?(index)
139
- puts "Ingnoring high diversity field #{header}"
297
+ puts "Ignoring high diversity field #{header}"
140
298
  else
141
299
  puts "Charting field: #{header} with length #{stats.length(index)} and diversity #{stats.diversity(index)}"
142
300
  hist = stats.stats[index]
@@ -156,5 +314,6 @@ $stats.each do |file,stats|
156
314
  end
157
315
  end
158
316
  end
317
+ end
159
318
  end
160
319
 
@@ -7,7 +7,7 @@ $: << '../lib'
7
7
  require 'date'
8
8
  require 'geoptima'
9
9
 
10
- Geoptima::assert_version("0.0.8")
10
+ Geoptima::assert_version("0.0.9")
11
11
 
12
12
  $debug=false
13
13
 
@@ -47,7 +47,8 @@ module Geoptima
47
47
  end
48
48
  def self.draw_histogram_chart(legend,keys,values,options={})
49
49
  puts "Creating a chart with legend #{legend} for #{keys.length} keys and #{values.length} values"
50
- g = make_chart(:bar, options)
50
+ chart_type = options[:side] ? :side_bar : :bar
51
+ g = make_chart(chart_type, options)
51
52
  g.data(legend, values)
52
53
  g.minimum_value = 0
53
54
  g.labels = keys.inject({}){|a,v| a[a.length] = v;a}
@@ -91,6 +92,8 @@ module Geoptima
91
92
  @chart.hide_lines = !options[:show_lines]
92
93
  when 'bar'
93
94
  @chart = Gruff::Bar.new(options[:width])
95
+ when 'side_bar'
96
+ @chart = Gruff::SideBar.new(options[:width])
94
97
  else
95
98
  raise "Unsupported chart type: #{chart_type}"
96
99
  end
@@ -45,6 +45,7 @@ module Geoptima
45
45
 
46
46
  def self.process_args(debug=nil)
47
47
  options = Options.new(debug)
48
+ options.add('v') {$print_version = true}
48
49
  options.add('d') {$debug = true}
49
50
  options.add('h') {$help = true}
50
51
  puts "Processing options: #{options}" if(debug)
@@ -58,6 +59,7 @@ module Geoptima
58
59
  options.args << arg
59
60
  end
60
61
  end
62
+ puts "Geoptima Gem Version: #{Geoptima::VERSION}" if($print_version)
61
63
  options.args
62
64
  end
63
65
 
@@ -1,6 +1,6 @@
1
1
  module Geoptima
2
2
 
3
- VERSION = "0.0.8"
3
+ VERSION = "0.0.9"
4
4
 
5
5
  def self.version_as_int(ver)
6
6
  base = 1
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoptima
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 8
10
- version: 0.0.8
9
+ - 9
10
+ version: 0.0.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Craig Taverner
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-19 00:00:00 +01:00
19
- default_executable:
18
+ date: 2012-03-21 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: multi_json
@@ -91,7 +90,6 @@ files:
91
90
  - CONTRIBUTORS
92
91
  - Gemfile
93
92
  - geoptima.gemspec
94
- has_rdoc: true
95
93
  homepage: http://github.com/craigtaverner/geoptima.rb
96
94
  licenses: []
97
95
 
@@ -129,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
127
  requirements: []
130
128
 
131
129
  rubyforge_project: geoptima
132
- rubygems_version: 1.6.2
130
+ rubygems_version: 1.7.2
133
131
  signing_key:
134
132
  specification_version: 3
135
133
  summary: Ruby access to Geoptima JSON files