geoptima 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|