argos-ruby 1.0.1 → 1.0.2

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/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: