argos-ruby 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,21 +2,17 @@
2
2
 
3
3
  A Ruby library for parsing Argos tracking data
4
4
 
5
- ```argos-ruby``` has been developed to parse [Argos](http://www.argos-system.org)
6
- satellite tracking data collected at the [Norwegian Polar Institute]
7
- (http://npolar.no/en) over a 25-year period (!) from 1989 to 2013.
5
+ [argos-ruby](https://github.com/npolar/argos-ruby) is used to parse [Argos](http://www.argos-system.org)
6
+ satellite tracking data files collected at the [Norwegian Polar Institute]
7
+ (http://npolar.no/en) since 1989.
8
8
 
9
9
  Be warned, the Argos file formats have changed over time. No promises are
10
10
  made that the library will work outside of Norway :).
11
11
 
12
- Currently, the library parses Argos DS/DIAG files dating from 1991
12
+ Currently, the library parses Argos DS/DIAG files dating from August 1990
13
13
  and onwards.
14
14
 
15
15
  ## Install
16
- Now
17
- $ git clone https://github.com/npolar/argos-ruby.git
18
-
19
- Soon
20
16
  $ gem install argos-ruby
21
17
 
22
18
  ## Command-line usage
data/bin/argos-ruby CHANGED
@@ -75,11 +75,17 @@ end
75
75
  log.debug "#{File.realpath(__FILE__)} #{param}"
76
76
  bundle = Digest::SHA1.hexdigest(glob+param[:filter].to_s)
77
77
  result = []
78
+ argosfiles = 0
78
79
 
79
- Dir[glob].select {|f|
80
- Argos.argos? f
81
- }.map {|filename|
80
+ Dir[glob].reject {|f| File.directory? f}.select {|f|
81
+ argosfiles = argosfiles + 1
82
+ if not Argos.argos? f
83
+ log.warn "Not Argos: #{f}"
84
+ end
82
85
 
86
+ Argos.argos? f
87
+ }.map {|filename|
88
+ log.debug "*"*80
83
89
  argos = Argos.factory(Argos.type(filename))
84
90
  argos.filename = filename
85
91
  argos.filter = param[:filter]
@@ -87,9 +93,7 @@ Dir[glob].select {|f|
87
93
 
88
94
  case param[:action]
89
95
  when "source"
90
-
91
96
  result << Argos.source(argos).merge(glob: glob, bundle: bundle)
92
-
93
97
  when "parse"
94
98
 
95
99
  arr = argos.parse(filename)
@@ -112,6 +116,8 @@ diag_count = result.select {|argos| argos[:type] == "diag"}.size
112
116
 
113
117
  if ["parse", "messages"].include? param[:action]
114
118
  log.info "Documents: #{result.size}, ds: #{ds_count}, diag: #{diag_count}, bundle: #{bundle}, glob: #{glob}"
119
+
120
+
115
121
  elsif "source" == param[:action]
116
122
  result = result.select {|s| s[:size] > 0 }
117
123
  sum_count = result.map {|s| s[:size]}.inject { |sum, c| sum + c }
@@ -119,13 +125,16 @@ elsif "source" == param[:action]
119
125
  s[:total] = sum_count
120
126
  s
121
127
  }
128
+ if argosfiles != result.size
129
+ log.fatal "Argos file count: #{argosfiles} differs from parsed files: #{result.size}"
130
+ end
122
131
  log.info "Documents (Σcount): #{sum_count}, sources: #{result.size} (ds: #{ds_count}, diag: #{diag_count}), bundle: #{bundle}, glob: #{glob}"
123
132
  end
124
133
 
125
134
  if param[:dest].nil?
126
135
  case param[:format]
127
136
  when "json"
128
- puts result.to_json
137
+ puts JSON.pretty_generate(result)
129
138
  when /y(a)?ml/
130
139
  puts result.to_yaml
131
140
  when /(ruby|rb)/
@@ -138,4 +147,4 @@ exit(0)
138
147
  rescue => e
139
148
  Logger.new(STDERR).fatal e
140
149
  exit(1)
141
- end
150
+ end
data/lib/argos/diag.rb CHANGED
@@ -17,9 +17,9 @@ module Argos
17
17
 
18
18
  LOCATION_CLASS = ["3", "2", "1", "0", "A", "B", "Z"]
19
19
 
20
- attr_accessor :log, :filename, :programs, :multiplicates
20
+ attr_accessor :log, :filename, :programs
21
21
 
22
- attr_reader :filename, :filter, :filtername, :sha1, :valid, :filesize
22
+ attr_reader :filename, :filter, :filtername, :sha1, :valid, :filesize, :updated, :multiplicates, :errors
23
23
 
24
24
  START_REGEX = /^\s*\d{5,6}\s+Date : \d{2}.\d{2}.\d{2} \d{2}:\d{2}:\d{2}/
25
25
  $start_diag ='^\s*\d{5,6}\s+Date : \d{2}.\d{2}.\d{2} \d{2}:\d{2}:\d{2}'
@@ -53,14 +53,8 @@ module Argos
53
53
  $FORMAT_3 =' *\d{5,6} +Date : (0[1-9]|[12][0-9]|3[01])\.(0[1-9]|1[012])\.\d{2} ([0-1][0-9]|2[0-3]):([0-5][0-9]:[0-5][0-9]) +LC : (3|2|1|0|A|B|Z) +IQ : *\d{2} *Lat1 : +((\d+\.\d{3}[NS])|\?+) +Lon1 : +((\d+\.\d{3}[EW])|\?+) +Lat2 : +((\d+\.\d{3}[NS])|\?)+ +Lon2 : +((\d+\.\d{3}[EW])|\?+) +Nb mes : (\d{3})? +Nb mes>-120dB : (\d{3})? +Best level : (-\d{3})? *dB +Pass duration : *(\d+|\?+) *s? +NOPC : +([0-4]|\?) +Calcul freq : +\d{3} (\d+\.\d+)? *Hz +Altitude : +(\d+)? m +.+E[+-]\d+( +(\d{2,5}|\w{2}))*$'
54
54
 
55
55
 
56
- def initialize (filename = nil)
57
- @index = 0
58
- @error_num = 0
59
- @errors_num =0
60
- @argos_contacts = Array.new
61
- @filename = filename
62
- read_file (filename) unless filename == nil
63
-
56
+ def initialize
57
+ @errors = []
64
58
  end
65
59
 
66
60
  def filter?
@@ -76,10 +70,7 @@ module Argos
76
70
  end
77
71
  end
78
72
 
79
- def get_hash
80
- @argos_contacts
81
- end
82
-
73
+ # @return []
83
74
  def parse(filename=nil)
84
75
  if filename.nil?
85
76
  filename = @filename
@@ -102,6 +93,7 @@ module Argos
102
93
  contact = []
103
94
  file = File.open(filename)
104
95
  @filesize = file.size
96
+ @updated = file.mtime
105
97
 
106
98
  log.debug "Parsing Argos DIAG file #{filename} sha1:#{sha1} (#{filesize} bytes)"
107
99
  if filter?
@@ -145,10 +137,11 @@ module Argos
145
137
 
146
138
  @multiplicates = group_by { |e| e }.select { |k, v| v.size > 1 }.map(&:first)
147
139
  if multiplicates.any?
148
- log.warn "Multiplicates (source sha1 #{sha1} #{filename}): #{multiplicates.to_json}"
140
+ #log.warn "#{multiplicates.size} multiplicates in source sha1 #{sha1} #{filename}): #{multiplicates.map {|a|a[:id]} }"
149
141
  self.uniq!
150
142
  log.info "Unique DIAG messages: #{self.size} sha1: #{sha1} #{filename}"
151
143
  end
144
+ self.sort_by! {|diag| diag[:measured]}
152
145
 
153
146
  self
154
147
  end
@@ -160,7 +153,8 @@ module Argos
160
153
  self << create_diag_hash(contact)
161
154
  true
162
155
  else
163
- error = "#{__FILE__}#check_format #{filename}:#{line_num} source:#{@sha1} Invalid format:\n" + contact
156
+ error = "#{filename}:#{line_num} sha1:#{@sha1} Invalid format:\n" + contact
157
+ @errors << error
164
158
  log.error error
165
159
  false
166
160
  end
@@ -229,7 +223,7 @@ module Argos
229
223
  sensor_data: sensor_data,
230
224
  technology: "argos",
231
225
  type: type,
232
- filename: filename,
226
+ location: "file://"+filename,
233
227
  source: "#{sha1}"
234
228
  }
235
229
 
data/lib/argos/ds.rb CHANGED
@@ -19,7 +19,7 @@ module Argos
19
19
 
20
20
  attr_writer :log, :filename
21
21
 
22
- attr_reader :filename, :filter, :filtername, :valid, :filesize, :sha1, :messages, :multiplicates
22
+ attr_reader :filename, :filter, :filtername, :valid, :filesize, :updated, :sha1, :messages, :multiplicates, :errors
23
23
 
24
24
  START_REGEX = /^\d{5} \d{5,6} +\d+ +\d+/
25
25
 
@@ -27,7 +27,8 @@ module Argos
27
27
 
28
28
  LOCATION_CLASS = [nil, "0","1","2","3","A","B","G","Z"]
29
29
 
30
- def self.ds? filename
30
+ def initialize
31
+ @errors = []
31
32
  end
32
33
 
33
34
  def filter?
@@ -78,7 +79,8 @@ module Argos
78
79
  contact = []
79
80
  file = File.open(filename)
80
81
  @filesize = file.size
81
-
82
+ @updated = file.mtime
83
+
82
84
  log.debug "Parsing ARGOS DS file #{filename} source:#{sha1} (#{filesize} bytes)"
83
85
  if filter?
84
86
  log.debug "Using filter: #{@filtername.nil? ? filter : @filtername }"
@@ -149,11 +151,11 @@ module Argos
149
151
 
150
152
  @multiplicates = group_by { |e| e }.select { |k, v| v.size > 1 }.map(&:first)
151
153
  if multiplicates.any?
152
- log.warn "Multiplicates (source sha1 #{sha1} #{filename}): #{multiplicates.to_json}"
154
+ log.warn "#{multiplicates.size} multiplicates in source sha1 #{sha1} #{filename}): #{multiplicates.map {|a|a[:id]} }"
153
155
  self.uniq!
154
156
  log.info "Unique DS messages: #{self.size} sha1: #{sha1} #{filename}"
155
157
  end
156
-
158
+ self.sort_by! {|ds| ds[:measured]}
157
159
  self
158
160
  end
159
161
 
@@ -303,11 +305,15 @@ module Argos
303
305
  unfolded
304
306
  end
305
307
 
308
+ # Merges a DS header hash into each measurement
309
+ # @return [Array] Measurements with header and static metadata merged in
306
310
  def merge(ds, measurement)
307
311
  m = ds.select {|k,v| k != :measurements and k != :errors and k != :warn }
308
312
  m = m.merge(measurement)
309
- m = m.merge({ technology: "argos",
310
- type: type, filename: filename, source: sha1
313
+ m = m.merge ({ technology: "argos",
314
+ type: type,
315
+ location: "file://"+filename,
316
+ source: sha1
311
317
  })
312
318
 
313
319
  if not ds[:errors].nil? and ds[:errors].any?
@@ -325,6 +331,27 @@ module Argos
325
331
  m[:warn] << "sensors-count-mismatch"
326
332
  end
327
333
 
334
+ # Create id as SHA1 hash of measurement minus stuff that may vary (like filename)
335
+ #
336
+ # Possible improvement for is to base id on a static list of keys
337
+ # :program,
338
+ # :platform,
339
+ # :lines,
340
+ # :sensors,
341
+ # :satellite,
342
+ # :lc,
343
+ # :positioned,
344
+ # :latitude,
345
+ # :longitude,
346
+ # :altitude,
347
+ # :headers,
348
+ # :measured,
349
+ # :identical,
350
+ # :sensor_data,
351
+ # :technology,
352
+ # :type,
353
+ # :source
354
+
328
355
  idbase = m.clone
329
356
  idbase.delete :errors
330
357
  idbase.delete :filename
data/lib/argos.rb CHANGED
@@ -16,7 +16,7 @@ require_relative "argos/diag"
16
16
  #
17
17
  # For information about Argos, see: http://www.argos-system.org
18
18
  module Argos
19
- VERSION = "1.0.1"
19
+ VERSION = "1.0.2"
20
20
  # Detect Argos type ("ds" or "diag" or nil)
21
21
  #
22
22
  # @param filename [String] Argos (DS or DIAG) file
@@ -116,15 +116,20 @@ module Argos
116
116
  west: argos.longitudes.min,
117
117
  latitude_mean: latitude_mean,
118
118
  longitude_mean: longitude_mean,
119
- filename: argos.filename,
120
- filesize: argos.filesize,
119
+ location: "file://"+argos.filename,
120
+ bytes: argos.filesize,
121
+ updated: argos.updated.xmlschema,
121
122
  messages: argos.messages.size,
122
123
  filter: argos.filtername.nil? ? argos.filter : argos.filtername,
123
- size: argos.size
124
+ size: argos.size,
125
+ parser: library_version
124
126
  }
125
127
  if argos.multiplicates.any?
126
128
  source[:multiplicates] = argos.multiplicates.map {|a| a[:id]}
127
129
  end
130
+ if argos.errors.any?
131
+ source[:errors] = argos.errors
132
+ end
128
133
  source
129
134
 
130
135
  end
@@ -0,0 +1,7 @@
1
+ 14759 Date : 28.08.91 13:47:39 LC : 1
2
+ Lat1 : 76.990N Lon1 : 22.232E Lat2 : 80.748N Lon2 : 37.670E
3
+ Nb mes : 005 Nb mes>-120dB : 004 Best level : -116 dB
4
+ Pass duration : 292s Dist track : 3
5
+ Calcul freq : 401 649728.9 Hz Altitude : 0 m
6
+ -.15686E+1 00 16 50
7
+ 14759 Date : 28.08.91 15:10:23 LC : 1
@@ -28,6 +28,10 @@ module Argos
28
28
  it "should return unique elements" do
29
29
  @diag.parse(diagfile("dup.diag")).size.should == 1
30
30
  end
31
+
32
+ it "should store errors" do
33
+ @diag.parse(diagfile("error.diag")).errors[0].should =~ /Invalid format/
34
+ end
31
35
 
32
36
  describe "#size" do
33
37
  it "should == number messages" do
@@ -55,8 +59,8 @@ module Argos
55
59
  :dist_track => nil,
56
60
  :technology=>"argos",
57
61
  :type=>"diag",
58
- :filename=>VALID_DIAG,
59
- :id => "a4e59580432b7b621f66c0cdc3087127554acd1d",
62
+ :location=>"file://"+VALID_DIAG,
63
+ :id => "ea2243d95df7d70a02a4fb66bc8876f10fdabf12",
60
64
  :parser => "argos-ruby-#{Argos::VERSION}",
61
65
  :source =>"f53ae3ab454f3e210347439aa440c084f775f9a4"}
62
66
  end
@@ -61,7 +61,7 @@ module Argos
61
61
  :sensor_data,
62
62
  :technology,
63
63
  :type,
64
- :filename,
64
+ :location,
65
65
  :source,
66
66
  :parser,
67
67
  :id]}
@@ -90,8 +90,8 @@ module Argos
90
90
  :positioned=>"1999-12-30T18:41:56Z", :latitude=>79.828,
91
91
  :longitude=>22.319, :altitude=>0.0, :headers=>12,
92
92
  :measured=>"1999-12-30T18:43:52Z", :identical=>3, :sensor_data=>["78", "00", "00"],
93
- :technology=>"argos", :type=>"ds", :filename=>VALID_DS, :parser => "argos-ruby-#{Argos::VERSION}",
94
- :source=>"3a39e0bd0b944dca4f4fbf17bc0680704cde2994", :id=>"4369c31c191bd55a998e6293ff4639da3984a95d"}]
93
+ :technology=>"argos", :type=>"ds", :location=>"file://"+VALID_DS, :parser => "argos-ruby-#{Argos::VERSION}",
94
+ :source=>"3a39e0bd0b944dca4f4fbf17bc0680704cde2994", :id=>"c78642c2bbfd4188df8940cd966b40cef33f2881"}]
95
95
  end
96
96
  end
97
97
  end
@@ -110,11 +110,11 @@ module Argos
110
110
  :latitude=>nil, :longitude=>nil, :altitude=>nil, :headers=>5,
111
111
  :measured=>"1999-12-16T00:46:49Z", :identical=>1,
112
112
  :sensor_data=>["92", "128", "130", "132"], :technology=>"argos",
113
- :type=>"ds", :filename=>VALID_DS,
113
+ :type=>"ds", :location=> "file://"+VALID_DS,
114
114
  :source=>"3a39e0bd0b944dca4f4fbf17bc0680704cde2994",
115
115
  :warn=>["missing-position", "sensors-count-mismatch"],
116
116
  :parser=>"argos-ruby-#{Argos::VERSION}",
117
- :id=>"f2c82a5ca1330b312925949a15ac300d07452a12"}]
117
+ :id=>"e81e2f255b62fa88e20351de8d5b2de9bf6b3028"}]
118
118
  end
119
119
 
120
120
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper.rb'
2
+
3
+ module Argos
4
+
5
+ describe Argos do
6
+ describe "source" do
7
+ context "DS 990660_A.DAT" do
8
+ ds = Ds.new
9
+ ds.log = Logger.new("/dev/null")
10
+ ds.parse dsfile("990660_A.DAT")
11
+ it do
12
+ Argos.source(ds).should == {:id=>"3a39e0bd0b944dca4f4fbf17bc0680704cde2994",
13
+ :technology=>"argos",
14
+ :collection=>"tracking",
15
+ :type=>"ds",
16
+ :programs=>[660, 9660],
17
+ :platforms=>[2167, 2168, 2170, 2173, 2174, 2176, 2179, 2180, 2188, 2189, 8567, 8571, 8574, 8576, 8578, 8579, 9678, 9686, 9692, 9693, 9694, 9696, 9698, 9699, 10618, 10619, 10622, 10783, 11104, 14747, 14765],
18
+ :start=>"1999-12-01T10:23:48Z",
19
+ :stop=>"1999-12-31T19:18:58Z",
20
+ :north=>79.866,
21
+ :east=>55.068,
22
+ :south=>75.822,
23
+ :west=>22.309,
24
+ :latitude_mean=>78.394,
25
+ :longitude_mean=>33.5,
26
+ :location=>"file://#{dsfile("990660_A.DAT")}",
27
+ :bytes=>107584,
28
+ :messages=>449,
29
+ :filter=>nil,
30
+ :size=>843,
31
+ :updated => "2013-10-21T19:02:32+02:00",
32
+ :parser=>Argos.library_version }
33
+ end
34
+ end
35
+ context "DS 990660_A.DIA" do
36
+ diag = Diag.new
37
+ diag.log = Logger.new("/dev/null")
38
+ diag.parse diagfile("990660_A.DIA")
39
+ it do
40
+ Argos.source(diag).should == {:id=>"f53ae3ab454f3e210347439aa440c084f775f9a4",
41
+ :technology=>"argos",
42
+ :collection=>"tracking",
43
+ :type=>"diag",
44
+ :programs=>[],
45
+ :platforms=>[2167, 2168, 2170, 2173, 2174, 2176, 2179, 2180, 2188, 2189, 8567, 8571, 8574, 8576, 8578, 8579, 9678, 9686, 9692, 9693, 9694, 9696, 9698, 9699, 10618, 10619, 10622, 10783, 11104, 14747, 14765],
46
+ :start=>"1999-12-01T10:24:54Z",
47
+ :stop=>"1999-12-31T19:18:58Z",
48
+ :north=>87.011,
49
+ :east=>65.27,
50
+ :south=>65.417,
51
+ :west=>-58.627,
52
+ :latitude_mean=>78.124,
53
+ :longitude_mean=>30.752,
54
+ :location=>"file://#{diagfile("990660_A.DIA")}",
55
+ :bytes=>222056,
56
+ :updated=>"2013-10-21T20:31:55+02:00",
57
+ :messages=>448,
58
+ :filter=>nil,
59
+ :size=>448,
60
+ :parser=>Argos.library_version}
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: argos-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-12-10 00:00:00.000000000 Z
13
+ date: 2014-01-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -48,12 +48,14 @@ files:
48
48
  - lib/argos/exception.rb
49
49
  - spec/argos/_diag/990660_A.DIA
50
50
  - spec/argos/_diag/dup.diag
51
+ - spec/argos/_diag/error.diag
51
52
  - spec/argos/_diag/valid_2009-03-02_DB_DIAG.txt
52
53
  - spec/argos/_ds/990660_A.DAT
53
54
  - spec/argos/_ds/dup.ds
54
55
  - spec/argos/_ds/sensor_mismatch_ds.txt
55
56
  - spec/argos/diag_spec.rb
56
57
  - spec/argos/ds_spec.rb
58
+ - spec/argos_spec.rb
57
59
  - spec/spec_helper.rb
58
60
  homepage: http://github.com/npolar/argos-ruby
59
61
  licenses: