geoptima 0.0.6 → 0.0.7
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 +132 -0
- data/bin/csv_stats +126 -0
- data/bin/show_geoptima +1 -5
- data/bin/show_geoptima_sos +50 -0
- data/examples/csv_chart.rb +132 -0
- data/examples/csv_stats.rb +126 -0
- data/examples/show_geoptima.rb +1 -5
- data/geoptima.gemspec +1 -1
- data/lib/geoptima/chart.rb +119 -0
- data/lib/geoptima/data.rb +55 -5
- data/lib/geoptima/options.rb +67 -0
- data/lib/geoptima/version.rb +1 -1
- data/lib/geoptima.rb +1 -0
- metadata +16 -7
- data/examples/export_layer.rb +0 -59
- data/examples/stats.rb +0 -41
data/bin/csv_chart
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# useful if being run inside a source code checkout
|
4
|
+
$: << 'lib'
|
5
|
+
$: << '../lib'
|
6
|
+
|
7
|
+
require 'geoptima/chart'
|
8
|
+
require 'geoptima/options'
|
9
|
+
|
10
|
+
$files = Geoptima::Options.process_args
|
11
|
+
|
12
|
+
class Stats
|
13
|
+
attr_reader :file, :imei, :headers, :stats, :data
|
14
|
+
def initialize(file,imei,fields)
|
15
|
+
@file = file
|
16
|
+
@imei = imei
|
17
|
+
@headers = fields
|
18
|
+
@stats = fields.map{|h| {}}
|
19
|
+
@data = fields.map{|h| []}
|
20
|
+
@numerical = fields.map{|h| true}
|
21
|
+
end
|
22
|
+
def add(field,index)
|
23
|
+
if field =~ /\w/
|
24
|
+
@numerical[index] &&= is_number?(field)
|
25
|
+
puts "\tField[#{index}]: #{field}" if($debug)
|
26
|
+
stats = @stats[index]
|
27
|
+
stats[field] ||= 0
|
28
|
+
stats[field] += 1
|
29
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
30
|
+
@data[index] << field
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def is_number?(field)
|
34
|
+
is_integer?(field) || is_float?(field)
|
35
|
+
end
|
36
|
+
def is_integer?(field)
|
37
|
+
field.to_i.to_s == field
|
38
|
+
end
|
39
|
+
def is_float?(field)
|
40
|
+
field.to_f.to_s == field
|
41
|
+
end
|
42
|
+
def length(index)
|
43
|
+
@stats[index].length
|
44
|
+
end
|
45
|
+
def diversity(index)
|
46
|
+
100.0 * @stats[index].length.to_f / @data[index].length.to_f
|
47
|
+
end
|
48
|
+
def diverse?(index)
|
49
|
+
@stats[index].length>500 || diversity(index) > 40.0
|
50
|
+
end
|
51
|
+
def numerical?(index)
|
52
|
+
@numerical[index]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
$stats = {}
|
57
|
+
|
58
|
+
$files.each do |file|
|
59
|
+
lines = 0
|
60
|
+
imei = file.split(/[_\.]/)[0]
|
61
|
+
File.open(file).each do |line|
|
62
|
+
lines += 1
|
63
|
+
fields=line.chomp.split(/\t/)
|
64
|
+
if $stats[file]
|
65
|
+
puts "Processing line: #{line}" if($debug)
|
66
|
+
fields.each_with_index do |field,index|
|
67
|
+
$stats[file].add(field,index)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
$stats[file] = Stats.new(file,imei,fields)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
$stats.each do |file,stats|
|
76
|
+
stats.headers.each_with_index do |header,index|
|
77
|
+
puts "Charting #{header} with diversity #{stats.diversity(index)}"
|
78
|
+
case header
|
79
|
+
when 'signal.strength'
|
80
|
+
Geoptima::Chart.draw_line_chart(
|
81
|
+
stats.imei,
|
82
|
+
stats.data[0],
|
83
|
+
stats.data[index].map{|f| v=f.to_i; (v>-130 && v<0) ? v : nil},
|
84
|
+
:title => 'Signal Strength',
|
85
|
+
:maximum_value => -30,
|
86
|
+
:minimum_value => -130,
|
87
|
+
:width => 1024
|
88
|
+
).write("Chart_#{stats.imei}_#{header}.png")
|
89
|
+
|
90
|
+
hist = stats.stats[index]
|
91
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
92
|
+
values = keys.map{|k| hist[k]}
|
93
|
+
Geoptima::Chart.draw_histogram_chart(
|
94
|
+
stats.imei, keys, values,
|
95
|
+
:title => 'Signal Strength Distribution',
|
96
|
+
:width => 1024
|
97
|
+
).write("Chart_#{stats.imei}_#{header}_distribution.png")
|
98
|
+
|
99
|
+
when 'Event'
|
100
|
+
hist = stats.stats[index]
|
101
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
102
|
+
values = keys.map{|k| hist[k]}
|
103
|
+
Geoptima::Chart.draw_category_chart(
|
104
|
+
stats.imei, keys, values,
|
105
|
+
:title => "#{header} Distribution",
|
106
|
+
:width => 1024
|
107
|
+
).write("Chart_#{stats.imei}_#{header}_distribution.png")
|
108
|
+
|
109
|
+
else
|
110
|
+
if stats.diverse?(index)
|
111
|
+
puts "Ingnoring high diversity field #{header}"
|
112
|
+
else
|
113
|
+
puts "Charting field: #{header} with length #{stats.length(index)} and diversity #{stats.diversity(index)}"
|
114
|
+
hist = stats.stats[index]
|
115
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
116
|
+
values = keys.map{|k| hist[k]}
|
117
|
+
args = [stats.imei, keys, values, {
|
118
|
+
:title => "#{header} Distribution",
|
119
|
+
:width => 1024}]
|
120
|
+
g = (stats.length(index) > 50) ?
|
121
|
+
Geoptima::Chart.draw_line_chart(*args) :
|
122
|
+
(stats.length(index) > 10 || stats.numerical?(index)) ?
|
123
|
+
Geoptima::Chart.draw_histogram_chart(*args) :
|
124
|
+
(stats.length(index) > 1) ?
|
125
|
+
Geoptima::Chart.draw_category_chart(*args) :
|
126
|
+
nil
|
127
|
+
g && g.write("Chart_#{stats.imei}_#{header}_distribution.png")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
data/bin/csv_stats
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# useful if being run inside a source code checkout
|
4
|
+
$: << 'lib'
|
5
|
+
$: << '../lib'
|
6
|
+
|
7
|
+
require 'geoptima/options'
|
8
|
+
|
9
|
+
$show_all = false
|
10
|
+
|
11
|
+
$files = Geoptima::Options.process_args do |option|
|
12
|
+
option.a {$show_all = true}
|
13
|
+
option.o {$output_files = true}
|
14
|
+
option.u {$exclude_stats = true}
|
15
|
+
option.I {$include_props = ARGV.shift.split(/[\,\;]+/)}
|
16
|
+
option.O {$output_prefix = ARGV.shift}
|
17
|
+
end
|
18
|
+
|
19
|
+
$help = true if($files.length<0)
|
20
|
+
if $help
|
21
|
+
puts <<EOHELP
|
22
|
+
Usage: ./stats.rb <-dha> <-I include_props> files
|
23
|
+
-d debug mode #{cw $debug}
|
24
|
+
-h print this help #{cw $help}
|
25
|
+
-a show all values, not just discrete ones #{cw $show_all}
|
26
|
+
-o output the stats to files instead of the console #{cw $output_files}
|
27
|
+
-u exclude stats, showing only unique lists of values #{cw $exclude_stats}
|
28
|
+
-I only calculate statistics for named properties #{aw $include_props}
|
29
|
+
-O prefix output files with specific prefix #{aw $output_prefix}
|
30
|
+
EOHELP
|
31
|
+
exit 0
|
32
|
+
end
|
33
|
+
|
34
|
+
$files.each do |file|
|
35
|
+
lines = 0
|
36
|
+
headers = nil
|
37
|
+
file_stats = nil
|
38
|
+
File.open(file).each do |line|
|
39
|
+
lines += 1
|
40
|
+
fields=line.chomp.split(/[\t\,]/)
|
41
|
+
if headers
|
42
|
+
puts "Processing line: #{line}" if($debug)
|
43
|
+
lac,ci=nil
|
44
|
+
fields.each_with_index do |field,index|
|
45
|
+
if $include_props.to_s=='' || $include_props.index(headers[index])
|
46
|
+
puts "\tField[#{index}]: #{field}" if($debug)
|
47
|
+
stats = file_stats[index]
|
48
|
+
stats[field] ||= 0
|
49
|
+
stats[field] += 1
|
50
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
51
|
+
lac=field if(headers[index]=='LAC' || headers[index]=='service.lac')
|
52
|
+
ci=field if(headers[index]=='CI' || headers[index]=='service.cell_id')
|
53
|
+
#puts "\tSet LAC=#{lac}, CI=#{ci} based on header #{headers[index]}" if($debug)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
puts "\tSet LAC=#{lac}, CI=#{ci}" if($debug)
|
57
|
+
if lac && ci
|
58
|
+
index = headers.length - 1
|
59
|
+
puts "\tAdding statistics for LAC=#{lac}, CI=#{ci} using additional header '#{headers[index]}'" if($debug)
|
60
|
+
stats = file_stats[index]
|
61
|
+
field="#{lac}-#{ci}"
|
62
|
+
stats[field] ||= 0
|
63
|
+
stats[field] += 1
|
64
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
65
|
+
end
|
66
|
+
if $debug
|
67
|
+
headers.each_with_index do |header,index|
|
68
|
+
stats = file_stats[index]
|
69
|
+
values = stats.keys
|
70
|
+
puts "\nFound #{values.length} unique values for field[#{index}] '#{header}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
headers = fields
|
75
|
+
headers << 'lac-ci'
|
76
|
+
file_stats = fields.map{|h| {}}
|
77
|
+
file_stats << {}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if headers
|
82
|
+
found=[]
|
83
|
+
empty=[]
|
84
|
+
headers.each_with_index do |header,index|
|
85
|
+
stats=file_stats[index]
|
86
|
+
found << [header,stats] if(stats.keys.length>0)
|
87
|
+
end
|
88
|
+
found.each do |ff|
|
89
|
+
header,stats=*ff
|
90
|
+
output = STDOUT
|
91
|
+
filename = ([$output_prefix,header,$exclude_stats ? "Values" : "Stats"]).compact.join('_')+".txt"
|
92
|
+
if $output_files
|
93
|
+
output = File.open(filename,'w')
|
94
|
+
end
|
95
|
+
values = stats.keys
|
96
|
+
perc = 100.0 * values.length.to_f / lines.to_f
|
97
|
+
puts "Found #{values.length} unique values for field '#{header}'"
|
98
|
+
if !$show_all && (values.length > 500)
|
99
|
+
puts "\tNot printing more values more diverse than 500"
|
100
|
+
elsif (!$show_all && (perc > 75))
|
101
|
+
puts "\tNot printing more values more diverse than #{perc}%"
|
102
|
+
else
|
103
|
+
output.puts header
|
104
|
+
values.sort.each do |value|
|
105
|
+
value_text = (value.to_s.length < 1) ? '<empty>' : value
|
106
|
+
if $exclude_stats
|
107
|
+
output.puts "\t#{value_text}"
|
108
|
+
else
|
109
|
+
output.puts "\t#{value_text}\t#{stats[value]}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
if $output_files
|
114
|
+
puts "\tSaved to #{filename}"
|
115
|
+
output.close
|
116
|
+
else
|
117
|
+
puts
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
puts "No headers found in file #{file}"
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
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.
|
10
|
+
Geoptima::assert_version("0.0.7")
|
11
11
|
|
12
12
|
$debug=false
|
13
13
|
|
@@ -15,10 +15,6 @@ $event_names=[]
|
|
15
15
|
$files = []
|
16
16
|
$print_limit = 10000
|
17
17
|
|
18
|
-
def cw(val)
|
19
|
-
val.nil? ? '' : "(#{val})"
|
20
|
-
end
|
21
|
-
|
22
18
|
while arg=ARGV.shift do
|
23
19
|
if arg =~ /^\-(\w+)/
|
24
20
|
$1.split(//).each do |aa|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# useful if being run inside a source code checkout
|
4
|
+
$: << 'lib'
|
5
|
+
$: << '../lib'
|
6
|
+
|
7
|
+
require 'date'
|
8
|
+
require 'geoptima'
|
9
|
+
|
10
|
+
$debug=false
|
11
|
+
|
12
|
+
$events={}
|
13
|
+
$files = []
|
14
|
+
|
15
|
+
$events={}
|
16
|
+
|
17
|
+
while arg=ARGV.shift:
|
18
|
+
if arg =~ /^\-(\w+)/
|
19
|
+
$1.split(//).each do |aa|
|
20
|
+
case aa
|
21
|
+
when 'd'
|
22
|
+
$debug=true
|
23
|
+
else
|
24
|
+
puts "Unrecognized option: -#{aa}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if File.exist? arg
|
29
|
+
$files << arg
|
30
|
+
else
|
31
|
+
puts "No such file: #{arg}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
$datasets = Geoptima::Dataset.make_datasets($files, :locate => true)
|
37
|
+
|
38
|
+
puts "Found #{$datasets.length} IMEIs"
|
39
|
+
$datasets.keys.sort.each do |imei|
|
40
|
+
dataset = $datasets[imei]
|
41
|
+
events = dataset.sorted('mode')
|
42
|
+
puts "\nFor #{imei} found #{dataset.length} events:\n"
|
43
|
+
if events && events.length>0
|
44
|
+
puts "Time\tLat\tLon\t#{events.first.header[1..-1].join("\t")}"
|
45
|
+
events.each do |event|
|
46
|
+
puts "#{event.time}\t#{event.latitude}\t#{event.longitude}\t#{event.data[1..-1].join("\t")}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# useful if being run inside a source code checkout
|
4
|
+
$: << 'lib'
|
5
|
+
$: << '../lib'
|
6
|
+
|
7
|
+
require 'geoptima/chart'
|
8
|
+
require 'geoptima/options'
|
9
|
+
|
10
|
+
$files = Geoptima::Options.process_args
|
11
|
+
|
12
|
+
class Stats
|
13
|
+
attr_reader :file, :imei, :headers, :stats, :data
|
14
|
+
def initialize(file,imei,fields)
|
15
|
+
@file = file
|
16
|
+
@imei = imei
|
17
|
+
@headers = fields
|
18
|
+
@stats = fields.map{|h| {}}
|
19
|
+
@data = fields.map{|h| []}
|
20
|
+
@numerical = fields.map{|h| true}
|
21
|
+
end
|
22
|
+
def add(field,index)
|
23
|
+
if field =~ /\w/
|
24
|
+
@numerical[index] &&= is_number?(field)
|
25
|
+
puts "\tField[#{index}]: #{field}" if($debug)
|
26
|
+
stats = @stats[index]
|
27
|
+
stats[field] ||= 0
|
28
|
+
stats[field] += 1
|
29
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
30
|
+
@data[index] << field
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def is_number?(field)
|
34
|
+
is_integer?(field) || is_float?(field)
|
35
|
+
end
|
36
|
+
def is_integer?(field)
|
37
|
+
field.to_i.to_s == field
|
38
|
+
end
|
39
|
+
def is_float?(field)
|
40
|
+
field.to_f.to_s == field
|
41
|
+
end
|
42
|
+
def length(index)
|
43
|
+
@stats[index].length
|
44
|
+
end
|
45
|
+
def diversity(index)
|
46
|
+
100.0 * @stats[index].length.to_f / @data[index].length.to_f
|
47
|
+
end
|
48
|
+
def diverse?(index)
|
49
|
+
@stats[index].length>500 || diversity(index) > 40.0
|
50
|
+
end
|
51
|
+
def numerical?(index)
|
52
|
+
@numerical[index]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
$stats = {}
|
57
|
+
|
58
|
+
$files.each do |file|
|
59
|
+
lines = 0
|
60
|
+
imei = file.split(/[_\.]/)[0]
|
61
|
+
File.open(file).each do |line|
|
62
|
+
lines += 1
|
63
|
+
fields=line.chomp.split(/\t/)
|
64
|
+
if $stats[file]
|
65
|
+
puts "Processing line: #{line}" if($debug)
|
66
|
+
fields.each_with_index do |field,index|
|
67
|
+
$stats[file].add(field,index)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
$stats[file] = Stats.new(file,imei,fields)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
$stats.each do |file,stats|
|
76
|
+
stats.headers.each_with_index do |header,index|
|
77
|
+
puts "Charting #{header} with diversity #{stats.diversity(index)}"
|
78
|
+
case header
|
79
|
+
when 'signal.strength'
|
80
|
+
Geoptima::Chart.draw_line_chart(
|
81
|
+
stats.imei,
|
82
|
+
stats.data[0],
|
83
|
+
stats.data[index].map{|f| v=f.to_i; (v>-130 && v<0) ? v : nil},
|
84
|
+
:title => 'Signal Strength',
|
85
|
+
:maximum_value => -30,
|
86
|
+
:minimum_value => -130,
|
87
|
+
:width => 1024
|
88
|
+
).write("Chart_#{stats.imei}_#{header}.png")
|
89
|
+
|
90
|
+
hist = stats.stats[index]
|
91
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
92
|
+
values = keys.map{|k| hist[k]}
|
93
|
+
Geoptima::Chart.draw_histogram_chart(
|
94
|
+
stats.imei, keys, values,
|
95
|
+
:title => 'Signal Strength Distribution',
|
96
|
+
:width => 1024
|
97
|
+
).write("Chart_#{stats.imei}_#{header}_distribution.png")
|
98
|
+
|
99
|
+
when 'Event'
|
100
|
+
hist = stats.stats[index]
|
101
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
102
|
+
values = keys.map{|k| hist[k]}
|
103
|
+
Geoptima::Chart.draw_category_chart(
|
104
|
+
stats.imei, keys, values,
|
105
|
+
:title => "#{header} Distribution",
|
106
|
+
:width => 1024
|
107
|
+
).write("Chart_#{stats.imei}_#{header}_distribution.png")
|
108
|
+
|
109
|
+
else
|
110
|
+
if stats.diverse?(index)
|
111
|
+
puts "Ingnoring high diversity field #{header}"
|
112
|
+
else
|
113
|
+
puts "Charting field: #{header} with length #{stats.length(index)} and diversity #{stats.diversity(index)}"
|
114
|
+
hist = stats.stats[index]
|
115
|
+
keys = hist.keys.sort{|a,b| a.to_i <=> b.to_i}
|
116
|
+
values = keys.map{|k| hist[k]}
|
117
|
+
args = [stats.imei, keys, values, {
|
118
|
+
:title => "#{header} Distribution",
|
119
|
+
:width => 1024}]
|
120
|
+
g = (stats.length(index) > 50) ?
|
121
|
+
Geoptima::Chart.draw_line_chart(*args) :
|
122
|
+
(stats.length(index) > 10 || stats.numerical?(index)) ?
|
123
|
+
Geoptima::Chart.draw_histogram_chart(*args) :
|
124
|
+
(stats.length(index) > 1) ?
|
125
|
+
Geoptima::Chart.draw_category_chart(*args) :
|
126
|
+
nil
|
127
|
+
g && g.write("Chart_#{stats.imei}_#{header}_distribution.png")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# useful if being run inside a source code checkout
|
4
|
+
$: << 'lib'
|
5
|
+
$: << '../lib'
|
6
|
+
|
7
|
+
require 'geoptima/options'
|
8
|
+
|
9
|
+
$show_all = false
|
10
|
+
|
11
|
+
$files = Geoptima::Options.process_args do |option|
|
12
|
+
option.a {$show_all = true}
|
13
|
+
option.o {$output_files = true}
|
14
|
+
option.u {$exclude_stats = true}
|
15
|
+
option.I {$include_props = ARGV.shift.split(/[\,\;]+/)}
|
16
|
+
option.O {$output_prefix = ARGV.shift}
|
17
|
+
end
|
18
|
+
|
19
|
+
$help = true if($files.length<0)
|
20
|
+
if $help
|
21
|
+
puts <<EOHELP
|
22
|
+
Usage: ./stats.rb <-dha> <-I include_props> files
|
23
|
+
-d debug mode #{cw $debug}
|
24
|
+
-h print this help #{cw $help}
|
25
|
+
-a show all values, not just discrete ones #{cw $show_all}
|
26
|
+
-o output the stats to files instead of the console #{cw $output_files}
|
27
|
+
-u exclude stats, showing only unique lists of values #{cw $exclude_stats}
|
28
|
+
-I only calculate statistics for named properties #{aw $include_props}
|
29
|
+
-O prefix output files with specific prefix #{aw $output_prefix}
|
30
|
+
EOHELP
|
31
|
+
exit 0
|
32
|
+
end
|
33
|
+
|
34
|
+
$files.each do |file|
|
35
|
+
lines = 0
|
36
|
+
headers = nil
|
37
|
+
file_stats = nil
|
38
|
+
File.open(file).each do |line|
|
39
|
+
lines += 1
|
40
|
+
fields=line.chomp.split(/[\t\,]/)
|
41
|
+
if headers
|
42
|
+
puts "Processing line: #{line}" if($debug)
|
43
|
+
lac,ci=nil
|
44
|
+
fields.each_with_index do |field,index|
|
45
|
+
if $include_props.to_s=='' || $include_props.index(headers[index])
|
46
|
+
puts "\tField[#{index}]: #{field}" if($debug)
|
47
|
+
stats = file_stats[index]
|
48
|
+
stats[field] ||= 0
|
49
|
+
stats[field] += 1
|
50
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
51
|
+
lac=field if(headers[index]=='LAC' || headers[index]=='service.lac')
|
52
|
+
ci=field if(headers[index]=='CI' || headers[index]=='service.cell_id')
|
53
|
+
#puts "\tSet LAC=#{lac}, CI=#{ci} based on header #{headers[index]}" if($debug)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
puts "\tSet LAC=#{lac}, CI=#{ci}" if($debug)
|
57
|
+
if lac && ci
|
58
|
+
index = headers.length - 1
|
59
|
+
puts "\tAdding statistics for LAC=#{lac}, CI=#{ci} using additional header '#{headers[index]}'" if($debug)
|
60
|
+
stats = file_stats[index]
|
61
|
+
field="#{lac}-#{ci}"
|
62
|
+
stats[field] ||= 0
|
63
|
+
stats[field] += 1
|
64
|
+
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
65
|
+
end
|
66
|
+
if $debug
|
67
|
+
headers.each_with_index do |header,index|
|
68
|
+
stats = file_stats[index]
|
69
|
+
values = stats.keys
|
70
|
+
puts "\nFound #{values.length} unique values for field[#{index}] '#{header}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
headers = fields
|
75
|
+
headers << 'lac-ci'
|
76
|
+
file_stats = fields.map{|h| {}}
|
77
|
+
file_stats << {}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if headers
|
82
|
+
found=[]
|
83
|
+
empty=[]
|
84
|
+
headers.each_with_index do |header,index|
|
85
|
+
stats=file_stats[index]
|
86
|
+
found << [header,stats] if(stats.keys.length>0)
|
87
|
+
end
|
88
|
+
found.each do |ff|
|
89
|
+
header,stats=*ff
|
90
|
+
output = STDOUT
|
91
|
+
filename = ([$output_prefix,header,$exclude_stats ? "Values" : "Stats"]).compact.join('_')+".txt"
|
92
|
+
if $output_files
|
93
|
+
output = File.open(filename,'w')
|
94
|
+
end
|
95
|
+
values = stats.keys
|
96
|
+
perc = 100.0 * values.length.to_f / lines.to_f
|
97
|
+
puts "Found #{values.length} unique values for field '#{header}'"
|
98
|
+
if !$show_all && (values.length > 500)
|
99
|
+
puts "\tNot printing more values more diverse than 500"
|
100
|
+
elsif (!$show_all && (perc > 75))
|
101
|
+
puts "\tNot printing more values more diverse than #{perc}%"
|
102
|
+
else
|
103
|
+
output.puts header
|
104
|
+
values.sort.each do |value|
|
105
|
+
value_text = (value.to_s.length < 1) ? '<empty>' : value
|
106
|
+
if $exclude_stats
|
107
|
+
output.puts "\t#{value_text}"
|
108
|
+
else
|
109
|
+
output.puts "\t#{value_text}\t#{stats[value]}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
if $output_files
|
114
|
+
puts "\tSaved to #{filename}"
|
115
|
+
output.close
|
116
|
+
else
|
117
|
+
puts
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
puts "No headers found in file #{file}"
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
data/examples/show_geoptima.rb
CHANGED
@@ -7,7 +7,7 @@ $: << '../lib'
|
|
7
7
|
require 'date'
|
8
8
|
require 'geoptima'
|
9
9
|
|
10
|
-
Geoptima::assert_version("0.0.
|
10
|
+
Geoptima::assert_version("0.0.7")
|
11
11
|
|
12
12
|
$debug=false
|
13
13
|
|
@@ -15,10 +15,6 @@ $event_names=[]
|
|
15
15
|
$files = []
|
16
16
|
$print_limit = 10000
|
17
17
|
|
18
|
-
def cw(val)
|
19
|
-
val.nil? ? '' : "(#{val})"
|
20
|
-
end
|
21
|
-
|
22
18
|
while arg=ARGV.shift do
|
23
19
|
if arg =~ /^\-(\w+)/
|
24
20
|
$1.split(//).each do |aa|
|
data/geoptima.gemspec
CHANGED
@@ -25,7 +25,7 @@ EOF
|
|
25
25
|
s.files = Dir.glob("{bin,lib,rdoc}/**/*").reject{|x| x=~/(tmp|target|test-data)/ || x=~/~$/} +
|
26
26
|
Dir.glob("examples/*rb") + Dir.glob("examples/sample*json") +
|
27
27
|
%w(README.rdoc CHANGELOG CONTRIBUTORS Gemfile geoptima.gemspec)
|
28
|
-
s.executables = ['show_geoptima','geoptima_file_time']
|
28
|
+
s.executables = ['show_geoptima','geoptima_file_time','csv_chart','csv_stats']
|
29
29
|
|
30
30
|
s.extra_rdoc_files = %w( README.rdoc )
|
31
31
|
s.rdoc_options = ["--quiet", "--title", "Geoptima.rb", "--line-numbers", "--main", "README.rdoc", "--inline-source"]
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
$chart_libs = ['gruff'].map do |chart_lib|
|
6
|
+
begin
|
7
|
+
require chart_lib
|
8
|
+
chart_lib
|
9
|
+
rescue LoadError
|
10
|
+
puts "Failed to load charting library '#{chart_lib}': #{$!}"
|
11
|
+
end
|
12
|
+
end.compact
|
13
|
+
|
14
|
+
if $chart_libs.length > 0
|
15
|
+
puts "Loaded #{$chart_libs.length} charting libraries: #{$chart_libs.join(', ')}"
|
16
|
+
else
|
17
|
+
puts "Warning: No charting libraries loaded. Chart support disabled."
|
18
|
+
puts "Please consider installing appropriate chart gems like 'gruff'"
|
19
|
+
end
|
20
|
+
|
21
|
+
module Geoptima
|
22
|
+
class Chart
|
23
|
+
DEFAULT_OPTIONS = {:show_points => true, :show_lines => true, :title => nil, :width => 800, :margins => 20, :font_size => 14}
|
24
|
+
attr_reader :chart_type
|
25
|
+
attr_accessor :chart, :data, :options
|
26
|
+
def initialize(chart_type,options={})
|
27
|
+
@chart_type = chart_type
|
28
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
29
|
+
end
|
30
|
+
def self.engine
|
31
|
+
@@engine ||= $chart_libs[0] || 'not available'
|
32
|
+
end
|
33
|
+
def self.engine=(name)
|
34
|
+
@@engine = $chart_libs.grep(/name/)[0] || engine
|
35
|
+
end
|
36
|
+
def self.line(options={})
|
37
|
+
make_chart(:line,options)
|
38
|
+
end
|
39
|
+
def self.draw_line_chart(legend,keys,values,options={})
|
40
|
+
g = make_chart(:line,{:show_points => false}.merge(options))
|
41
|
+
g.data(legend, values)
|
42
|
+
g.labels= {0=>keys[0], (keys.length-1)=>keys[-1]}
|
43
|
+
options[:maximum_value] && g.maximum_value = options[:maximum_value].to_i
|
44
|
+
options[:minimum_value] && g.minimum_value = options[:minimum_value].to_i
|
45
|
+
options[:filename] && g.write(options[:filename])
|
46
|
+
g
|
47
|
+
end
|
48
|
+
def self.draw_histogram_chart(legend,keys,values,options={})
|
49
|
+
puts "Creating a chart with legend #{legend} for #{keys.length} keys and #{values.length} values"
|
50
|
+
g = make_chart(:bar, options)
|
51
|
+
g.data(legend, values)
|
52
|
+
g.minimum_value = 0
|
53
|
+
g.labels = keys.inject({}){|a,v| a[a.length] = v;a}
|
54
|
+
options[:filename] && g.write(options[:filename])
|
55
|
+
g
|
56
|
+
end
|
57
|
+
def self.draw_category_chart(legend,keys,values,options={})
|
58
|
+
puts "Creating category chart with keys: #{keys.join(',')}"
|
59
|
+
puts "Creating category chart with values: #{values.join(',')}"
|
60
|
+
g = make_chart(:bar, options)
|
61
|
+
keys.each_with_index do |key,index|
|
62
|
+
puts "\t Adding category #{key} with value #{values[index]}"
|
63
|
+
g.data(key, values[index])
|
64
|
+
end
|
65
|
+
g.minimum_value = 0
|
66
|
+
options[:filename] && g.write(options[:filename])
|
67
|
+
g
|
68
|
+
end
|
69
|
+
def self.bar(options={})
|
70
|
+
make_chart(:bar,options)
|
71
|
+
end
|
72
|
+
def self.make_chart(chart_type,options={})
|
73
|
+
case engine
|
74
|
+
when 'gruff'
|
75
|
+
GruffChart.new(chart_type,options)
|
76
|
+
else
|
77
|
+
puts "Unsupported chart engine: #{@@engine}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
class GruffChart < Chart
|
82
|
+
def initialize(chart_type,options={})
|
83
|
+
super(chart_type,options)
|
84
|
+
end
|
85
|
+
def chart
|
86
|
+
unless @chart
|
87
|
+
case chart_type.to_s
|
88
|
+
when 'line'
|
89
|
+
@chart = Gruff::Line.new(options[:width])
|
90
|
+
@chart.hide_dots = !options[:show_points]
|
91
|
+
@chart.hide_lines = !options[:show_lines]
|
92
|
+
when 'bar'
|
93
|
+
@chart = Gruff::Bar.new(options[:width])
|
94
|
+
else
|
95
|
+
raise "Unsupported chart type: #{chart_type}"
|
96
|
+
end
|
97
|
+
@chart.title = options[:title]
|
98
|
+
@chart.margins = options[:margins]
|
99
|
+
@chart.legend_font_size = options[:font_size]
|
100
|
+
@chart.marker_font_size = options[:font_size]
|
101
|
+
@chart.title_font_size = options[:title_font_size] || 2 * options[:font_size]
|
102
|
+
end
|
103
|
+
@chart
|
104
|
+
end
|
105
|
+
def data(name,values)
|
106
|
+
chart.data(name,values)
|
107
|
+
end
|
108
|
+
def labels=(label_map)
|
109
|
+
chart.labels = label_map
|
110
|
+
end
|
111
|
+
def method_missing(symbol,*args,&block)
|
112
|
+
chart.send symbol, *args, &block
|
113
|
+
end
|
114
|
+
def write(filename)
|
115
|
+
chart.write(filename)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
data/lib/geoptima/data.rb
CHANGED
@@ -3,6 +3,20 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'multi_json'
|
5
5
|
require 'date'
|
6
|
+
if $use_dateperformance
|
7
|
+
begin
|
8
|
+
require 'date/performance'
|
9
|
+
require 'date/memoize'
|
10
|
+
class DateTime
|
11
|
+
def >(other) ; self - other > 0 ; end
|
12
|
+
def <(other) ; self - other < 0 ; end
|
13
|
+
def >=(other); self - other >= 0; end
|
14
|
+
def <=(other); self - other <= 0; end
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "No date-performance gem installed, some features will run slower"
|
18
|
+
end
|
19
|
+
end
|
6
20
|
|
7
21
|
#
|
8
22
|
# The Geoptima Module provides support for the Geoptima Client JSON file format
|
@@ -29,6 +43,26 @@ module Geoptima
|
|
29
43
|
end
|
30
44
|
end
|
31
45
|
|
46
|
+
class DateRange
|
47
|
+
attr_reader :min, :max, :range
|
48
|
+
def initialize(min,max)
|
49
|
+
@min = min
|
50
|
+
@max = max
|
51
|
+
@range = Range.new(min,max)
|
52
|
+
end
|
53
|
+
if ENV['RUBY_VERSION'] =~ /1\.8/
|
54
|
+
puts "Defining Range.include? to wrap for 1.8"
|
55
|
+
def include?(time)
|
56
|
+
@range.include?(time)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
puts "Defining Range.include? to perform inequality tests for 1.9"
|
60
|
+
def include?(time)
|
61
|
+
(time >= min) && (time <= @max)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
32
66
|
# The Geoptima::Event class represents and individual record or event
|
33
67
|
class Event
|
34
68
|
KNOWN_HEADERS={
|
@@ -67,7 +101,7 @@ module Geoptima
|
|
67
101
|
time.new_offset(0)
|
68
102
|
end
|
69
103
|
def time_key
|
70
|
-
utc.strftime("%Y-%m-%d %H:%M:%S.%3N")
|
104
|
+
utc.strftime("%Y-%m-%d %H:%M:%S.%3N").gsub(/\.(\d{3})\d+/,'.\1')
|
71
105
|
end
|
72
106
|
def [](key)
|
73
107
|
@fields[key] || @fields[key.gsub(/#{name}\./,'')]
|
@@ -127,7 +161,7 @@ module Geoptima
|
|
127
161
|
@fields[key] ||= subscriber[key] || subscriber[key.downcase]
|
128
162
|
end
|
129
163
|
def start
|
130
|
-
@start ||= subscriber['start'] && DateTime.parse(subscriber['start'].gsub(/Asia\/Bangkok/,'GMT+7')
|
164
|
+
@start ||= subscriber['start'] && DateTime.parse(subscriber['start'].gsub(/Asia\/Bangkok/,'GMT+7'))#.gsub(/Mar 17 2044/,'Feb 14 2012'))
|
131
165
|
end
|
132
166
|
def valid?
|
133
167
|
start && start > Data.min_start && start < Data.max_start
|
@@ -216,7 +250,7 @@ module Geoptima
|
|
216
250
|
@imei = imei
|
217
251
|
@data = []
|
218
252
|
@options = options
|
219
|
-
@time_range = options[:time_range] ||
|
253
|
+
@time_range = options[:time_range] || DateRange.new(Config[:min_datetime],Config[:max_datetime])
|
220
254
|
@fields = {}
|
221
255
|
end
|
222
256
|
|
@@ -347,17 +381,30 @@ module Geoptima
|
|
347
381
|
@sorted ||= {}
|
348
382
|
unless @sorted[nil]
|
349
383
|
event_hash = {}
|
384
|
+
puts "Creating sorted maps for #{self}" if($debug)
|
350
385
|
events_names.each do |name|
|
386
|
+
puts "Preparing maps for #{name}" if($debug)
|
351
387
|
@data.each do |data|
|
388
|
+
puts "Processing #{(e=data.events[name]) && e.length} events for #{name}" if($debug)
|
352
389
|
(events = data.events[name]) && events.each do |event|
|
390
|
+
# t = event.time.to_i
|
391
|
+
puts "\t\tTesting #{event.time} inside #{@time_range}" if($debug)
|
392
|
+
# if t < tmax
|
393
|
+
# if event.time > @time_range.min
|
394
|
+
# if (event.time >= @time_range.min) && (event.time < @time_range.max)
|
353
395
|
if @time_range.include?(event.time)
|
396
|
+
# if @time_range.cover?(event.time)
|
397
|
+
puts "\t\t\tEvent at #{event.time} is inside #{@time_range}" if($debug)
|
354
398
|
key = "#{event.time_key} #{name}"
|
355
399
|
event_hash[key] = event
|
356
400
|
end
|
357
401
|
end
|
358
402
|
end
|
403
|
+
puts "After adding #{name} events, maps are #{event_hash.length} long" if($debug)
|
359
404
|
end
|
405
|
+
puts "Merging and sorting #{event_hash.keys.length} maps" if($debug)
|
360
406
|
@sorted[nil] = event_hash.keys.sort.map{|k| event_hash[k]}
|
407
|
+
puts "Sorted #{@sorted[nil].length} events" if($debug)
|
361
408
|
locate_events if(options[:locate])
|
362
409
|
end
|
363
410
|
@sorted
|
@@ -365,18 +412,21 @@ module Geoptima
|
|
365
412
|
|
366
413
|
def locate_events
|
367
414
|
prev_gps = nil
|
415
|
+
count = 0
|
416
|
+
puts "Locating #{sorted.length} events" if($debug)
|
368
417
|
sorted.each do |event|
|
369
418
|
if event.name === 'gps'
|
370
419
|
event.locate(event)
|
371
420
|
prev_gps = event
|
372
421
|
elsif prev_gps
|
373
|
-
event.locate_if_closer_than(prev_gps,60)
|
422
|
+
count += 1 if(event.locate_if_closer_than(prev_gps,60))
|
374
423
|
end
|
375
424
|
end
|
425
|
+
puts "Located #{count} / #{sorted.length} events" if($debug)
|
376
426
|
end
|
377
427
|
|
378
428
|
def to_s
|
379
|
-
"IMEI:#{imei}, IMSI:#{imsis.join(',')}, Platform:#{platform}, Model:#{model}, OS:#{os}, Files:#{file_count}, Events:#{sorted.length}"
|
429
|
+
"IMEI:#{imei}, IMSI:#{imsis.join(',')}, Platform:#{platform}, Model:#{model}, OS:#{os}, Files:#{file_count}, Events:#{sorted && sorted.length}"
|
380
430
|
end
|
381
431
|
|
382
432
|
def self.make_datasets(files, options={})
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
def cw(val)
|
4
|
+
val.nil? ? '' : "(#{val})"
|
5
|
+
end
|
6
|
+
|
7
|
+
def aw(val)
|
8
|
+
val.nil? ? '' : "#{val.inspect}"
|
9
|
+
end
|
10
|
+
|
11
|
+
module Geoptima
|
12
|
+
|
13
|
+
class Options
|
14
|
+
|
15
|
+
attr_reader :args, :options, :debug
|
16
|
+
|
17
|
+
def initialize(debug=nil)
|
18
|
+
@debug = debug
|
19
|
+
@args = []
|
20
|
+
@options = {}
|
21
|
+
end
|
22
|
+
def add(*args,&block)
|
23
|
+
puts "Adding option processing for: #{args[0]}" if(debug)
|
24
|
+
@options[args[0].to_s] = block
|
25
|
+
end
|
26
|
+
def method_missing(symbol,*args,&block)
|
27
|
+
puts "Adding option processing for: #{symbol}" if(debug)
|
28
|
+
@options[symbol.to_s] = block
|
29
|
+
end
|
30
|
+
def process(a)
|
31
|
+
puts "Looking for match to option #{a}" if(debug)
|
32
|
+
@options.each do |opt,block|
|
33
|
+
puts "Comparing option #{a} to known option #{opt}" if(debug)
|
34
|
+
if opt === a
|
35
|
+
puts "Calling block for option #{a}: #{block.inspect}" if(debug)
|
36
|
+
block.call
|
37
|
+
return
|
38
|
+
end
|
39
|
+
end
|
40
|
+
puts "Unknown option: -#{a}"
|
41
|
+
end
|
42
|
+
def to_s
|
43
|
+
"Options[#{@options.keys.sort.join(', ')}]: #{args.join(', ')}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.process_args(debug=nil)
|
47
|
+
options = Options.new(debug)
|
48
|
+
options.add('d') {$debug = true}
|
49
|
+
options.add('h') {$help = true}
|
50
|
+
puts "Processing options: #{options}" if(debug)
|
51
|
+
yield options if(block_given?)
|
52
|
+
while arg = ARGV.shift do
|
53
|
+
if arg =~ /^\-(\w+)/
|
54
|
+
$1.split(//).each do |a|
|
55
|
+
options.process a
|
56
|
+
end
|
57
|
+
else
|
58
|
+
options.args << arg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
options.args
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
data/lib/geoptima/version.rb
CHANGED
data/lib/geoptima.rb
CHANGED
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:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Craig Taverner
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-19 00:00:00 +01:00
|
19
|
+
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: multi_json
|
@@ -62,27 +63,35 @@ email: craig@amanzi.com
|
|
62
63
|
executables:
|
63
64
|
- show_geoptima
|
64
65
|
- geoptima_file_time
|
66
|
+
- csv_chart
|
67
|
+
- csv_stats
|
65
68
|
extensions: []
|
66
69
|
|
67
70
|
extra_rdoc_files:
|
68
71
|
- README.rdoc
|
69
72
|
files:
|
73
|
+
- bin/show_geoptima_sos
|
70
74
|
- bin/show_geoptima
|
75
|
+
- bin/csv_chart
|
71
76
|
- bin/geoptima_file_time
|
77
|
+
- bin/csv_stats
|
72
78
|
- lib/geoptima/version.rb
|
73
79
|
- lib/geoptima/data.rb
|
80
|
+
- lib/geoptima/chart.rb
|
81
|
+
- lib/geoptima/options.rb
|
74
82
|
- lib/geoptima.rb
|
75
83
|
- examples/show_geoptima_sos.rb
|
76
|
-
- examples/export_layer.rb
|
77
|
-
- examples/stats.rb
|
78
84
|
- examples/show_geoptima.rb
|
85
|
+
- examples/csv_chart.rb
|
79
86
|
- examples/geoptima_file_time.rb
|
87
|
+
- examples/csv_stats.rb
|
80
88
|
- examples/sample_geoptima.json
|
81
89
|
- README.rdoc
|
82
90
|
- CHANGELOG
|
83
91
|
- CONTRIBUTORS
|
84
92
|
- Gemfile
|
85
93
|
- geoptima.gemspec
|
94
|
+
has_rdoc: true
|
86
95
|
homepage: http://github.com/craigtaverner/geoptima.rb
|
87
96
|
licenses: []
|
88
97
|
|
@@ -120,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
129
|
requirements: []
|
121
130
|
|
122
131
|
rubyforge_project: geoptima
|
123
|
-
rubygems_version: 1.
|
132
|
+
rubygems_version: 1.6.2
|
124
133
|
signing_key:
|
125
134
|
specification_version: 3
|
126
135
|
summary: Ruby access to Geoptima JSON files
|
data/examples/export_layer.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
#!/usr/bin/env jruby
|
2
|
-
|
3
|
-
# useful if being run inside a source code checkout
|
4
|
-
$: << 'lib'
|
5
|
-
$: << '../lib'
|
6
|
-
|
7
|
-
require 'rubygems'
|
8
|
-
require 'neo4j/spatial'
|
9
|
-
require 'neo4j/spatial/cmd'
|
10
|
-
|
11
|
-
$zoom = 1.0
|
12
|
-
$args = Neo4j::Spatial::Cmd.args
|
13
|
-
|
14
|
-
if $list === 'layers'
|
15
|
-
layers = Neo4j::Spatial::Layer.list
|
16
|
-
puts "Have #{layers.length} existing layers in the database:"
|
17
|
-
layers.each {|l| puts "\t#{l} (#{l.type_name})"}
|
18
|
-
puts
|
19
|
-
exit 0
|
20
|
-
end
|
21
|
-
|
22
|
-
if $help || $args.length < 1
|
23
|
-
puts <<-eos
|
24
|
-
|
25
|
-
usage: ./export_layer.rb <-D storage_path> <-F format> <-E dir> <-Z zoom> <-W width> <-H height> <-l> <-h> layer <layers>
|
26
|
-
-D Use specified database location
|
27
|
-
-F Use specified export format (png, shp)
|
28
|
-
-E Use specified export directory path (default '.')
|
29
|
-
-Z Zoom in by specified factor (eg. 3.0)
|
30
|
-
-W Image width (default 600)
|
31
|
-
-H Image height (default 400)
|
32
|
-
-l List existing database layers first
|
33
|
-
-h Display this help and exit
|
34
|
-
The layer(s) should be pre-existing layers (including dynamic layers) in the database.
|
35
|
-
Supported formats are 'shp' for ESRI Shapefile and 'png' for images.
|
36
|
-
|
37
|
-
For example:
|
38
|
-
./export_layer.rb -D db -E exports -F png croatia.osm highway highway-residential natural-water
|
39
|
-
|
40
|
-
This will export four previously defined layers to png format files in the 'exports' directory.
|
41
|
-
|
42
|
-
eos
|
43
|
-
exit
|
44
|
-
end
|
45
|
-
|
46
|
-
if $format.to_s.downcase === 'shp'
|
47
|
-
$exporter = Neo4j::Spatial::SHPExporter.new :dir => $export
|
48
|
-
else
|
49
|
-
$exporter = Neo4j::Spatial::ImageExporter.new :dir => $export, :zoom => $zoom, :width => $width, :height => $height
|
50
|
-
end
|
51
|
-
|
52
|
-
puts "Exporting #{$args.length} layers to #{$exporter.format}"
|
53
|
-
|
54
|
-
$args.each do |layer|
|
55
|
-
l = Neo4j::Spatial::Layer.find layer
|
56
|
-
puts "Exporting #{l} (#{l.type_name}) - #{l.index.layer_bounding_box}"
|
57
|
-
$exporter.export l.name
|
58
|
-
puts "Finished exporting #{l} (#{l.type_name}) of #{l.index.count} entries"
|
59
|
-
end
|
data/examples/stats.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$debug = false
|
4
|
-
$lines = 0
|
5
|
-
|
6
|
-
ARGF.each do |line|
|
7
|
-
$lines += 1
|
8
|
-
fields=line.chomp.split(/\t/)
|
9
|
-
if $headers
|
10
|
-
puts "Processing line: #{line}" if($debug)
|
11
|
-
fields.each_with_index do |field,index|
|
12
|
-
puts "\tField[#{index}]: #{field}" if($debug)
|
13
|
-
stats = $stats[index]
|
14
|
-
stats[field] ||= 0
|
15
|
-
stats[field] += 1
|
16
|
-
puts "\tField[#{index}]: #{field} => #{stats[field]}" if($debug)
|
17
|
-
end
|
18
|
-
else
|
19
|
-
$headers = fields
|
20
|
-
$stats = fields.map{|h| {}}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
$headers.each_with_index do |header,index|
|
25
|
-
stats = $stats[index]
|
26
|
-
values = stats.keys
|
27
|
-
perc = 100.0 * values.length.to_f / $lines.to_f
|
28
|
-
puts "\nFound #{values.length} unique values for field '#{header}'"
|
29
|
-
if values.length > 500
|
30
|
-
puts "\tNot printing more values more diverse than 500"
|
31
|
-
elsif (perc > 75)
|
32
|
-
puts "\tNot printing more values more diverse than #{perc}%"
|
33
|
-
else
|
34
|
-
puts header
|
35
|
-
values.sort.each do |value|
|
36
|
-
value_text = (value.to_s.length < 1) ? '<empty>' : value
|
37
|
-
puts "\t#{value_text}\t#{stats[value]}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|