seis_ruby 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/seis_ruby +17 -0
- data/lib/seis_ruby/data/cmtsolution.rb +62 -0
- data/lib/seis_ruby/data/sac.rb +6 -0
- data/lib/seis_ruby/data.rb +6 -0
- data/lib/seis_ruby/io/gcmt_catalog/custom_html_parser.rb +13 -0
- data/lib/seis_ruby/io/gcmt_catalog.rb +42 -0
- data/lib/seis_ruby/io.rb +5 -0
- data/lib/seis_ruby/version.rb +3 -0
- data/lib/seis_ruby.rb +5 -0
- data/rakefile +8 -0
- data/seis_ruby.gemspec +18 -0
- data/spec/seis_ruby/data/cmtsolution_spec.rb +98 -0
- data/spec/seis_ruby/io/gcmt_catalog_spec.rb +20 -0
- data/spec/seis_ruby/io/scrape.yaml +3970 -0
- data/spec/spec_helper.rb +16 -0
- metadata +121 -0
data/bin/seis_ruby
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
class SeisRubyRunner < Thor
|
5
|
+
require 'seis_ruby'
|
6
|
+
require 'ruby_patch'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
desc 'gcmt_catalog_scrape URL', 'scrape cmtsolution data from GCMT catalog search result pages.'
|
10
|
+
def gcmt_catalog_scrape(url)
|
11
|
+
file = "#{__METHOD__}_#{Time.now.ymdhms}.yaml"
|
12
|
+
open(file, 'w').write(SeisRuby::Io::GcmtCatalog.scrape(url).to_yaml)
|
13
|
+
puts file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
SeisRubyRunner.start
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module SeisRuby
|
2
|
+
module Data
|
3
|
+
module Cmtsolution
|
4
|
+
require 'rainbow'
|
5
|
+
require 'ruby_patch/string'
|
6
|
+
|
7
|
+
ParseError = Class.new(StandardError)
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def _preprocess_for_parse(text_for_one_event)
|
12
|
+
text_for_one_event\
|
13
|
+
.sub(/\A\n*/, '')\
|
14
|
+
.sub(/\n*\z/, '')\
|
15
|
+
.split("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def _parse_lines(lines)
|
19
|
+
h = {hypocenter: {}, centroid: {}}
|
20
|
+
|
21
|
+
line0 = lines[0]
|
22
|
+
h[:hypocenter][:data_source] = line0[0..4].strip
|
23
|
+
line0_rest = line0[5..-1].split
|
24
|
+
[:year, :month, :day, :hour, :minute].each{|k|
|
25
|
+
raise ParseError if line0_rest.empty?
|
26
|
+
h[:hypocenter][k] = line0_rest.shift.to_i
|
27
|
+
}
|
28
|
+
[:second, :latitude, :longitude, :depth, :mb, :ms].each{|k|
|
29
|
+
raise ParseError if line0_rest.empty?
|
30
|
+
h[:hypocenter][k] = line0_rest.shift.to_f
|
31
|
+
}
|
32
|
+
h[:hypocenter][:region_name] = line0_rest.join(' ')
|
33
|
+
h[:event_name] = lines[1].split(':')[1].strip
|
34
|
+
values = lines[2..-1].map{|line| line.split(':')[1].to_f}
|
35
|
+
[
|
36
|
+
:time_shift, :half_duration,
|
37
|
+
:latitude, :longitude, :depth,
|
38
|
+
:mrr, :mtt, :mpp, :mrt, :mrp, :mtp,
|
39
|
+
].zip(values).each{|k, v| h[:centroid][k] = v}
|
40
|
+
|
41
|
+
|
42
|
+
h
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse(text_for_one_event)
|
46
|
+
begin
|
47
|
+
lines = _preprocess_for_parse(text_for_one_event)
|
48
|
+
_parse_lines(lines)
|
49
|
+
rescue
|
50
|
+
raise ParseError, text_for_one_event\
|
51
|
+
.split("\n")\
|
52
|
+
.map{|line| line.quote('|'.color(:red))}\
|
53
|
+
.join("\n")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_list(events)
|
58
|
+
events.map{|ev| parse(ev)}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SeisRuby
|
2
|
+
module Io
|
3
|
+
module GcmtCatalog
|
4
|
+
require 'mechanize'
|
5
|
+
|
6
|
+
class CustomHtmlParser < ::Mechanize::Page
|
7
|
+
def initialize(uri = nil, response = nil, body = nil, code = nil, mech = nil)
|
8
|
+
super(uri, response, body.gsub(/<=/, '<='), code, mech)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SeisRuby
|
2
|
+
module Io
|
3
|
+
module GcmtCatalog
|
4
|
+
require 'rainbow'
|
5
|
+
require 'mechanize'
|
6
|
+
require 'seis_ruby/io/gcmt_catalog/custom_html_parser'
|
7
|
+
require 'seis_ruby/data/cmtsolution'
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def scrape(url)
|
12
|
+
agent = Mechanize.new{|a|
|
13
|
+
a.pluggable_parser.html = ::SeisRuby::Io::GcmtCatalog::CustomHtmlParser
|
14
|
+
}
|
15
|
+
|
16
|
+
event_list = []
|
17
|
+
while url
|
18
|
+
agent.get(url)
|
19
|
+
agent.page.search('pre')\
|
20
|
+
.find{|e| e.text =~ /event name:/}\
|
21
|
+
.text.split("\n\n")\
|
22
|
+
.each{|event|
|
23
|
+
begin
|
24
|
+
event_list << ::SeisRuby::Data::Cmtsolution.parse(event) unless event.strip.empty?
|
25
|
+
rescue ::SeisRuby::Data::Cmtsolution::ParseError => e
|
26
|
+
$stderr.puts e.class.to_s.color(:red)
|
27
|
+
$stderr.puts e.message
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
url = nil
|
32
|
+
if next_link = agent.page.links\
|
33
|
+
.find{|e| e.text == 'More solutions'}
|
34
|
+
url = next_link.uri
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
event_list
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/seis_ruby/io.rb
ADDED
data/lib/seis_ruby.rb
ADDED
data/rakefile
ADDED
data/seis_ruby.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
gem_name = File.basename(Dir.pwd)
|
2
|
+
require "./lib/#{gem_name}/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.files = `git ls-files`.split
|
6
|
+
s.name = gem_name
|
7
|
+
s.summary = "Ruby library for earthquake science."
|
8
|
+
s.version = SeisRuby::VERSION
|
9
|
+
s.add_development_dependency 'rspec', '~> 2'
|
10
|
+
s.add_development_dependency 'simplecov', '~> 0'
|
11
|
+
s.add_runtime_dependency 'rainbow', '~>1'
|
12
|
+
s.add_runtime_dependency 'mechanize', '~>2'
|
13
|
+
s.add_runtime_dependency 'ruby_patch', ['>= 0.1.0', '< 1.0.0']
|
14
|
+
s.author = 'kshramt'
|
15
|
+
s.description = "Ruby library for earthquake science. Provides Parser for various data formats used in seismology."
|
16
|
+
s.required_ruby_version = '>= 1.9.0'
|
17
|
+
s.test_files.concat `git ls-files spec`.split.select{|path| path =~ /_spec\.rb/}
|
18
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'seis_ruby/data/cmtsolution'
|
3
|
+
|
4
|
+
describe ::SeisRuby::Data::Cmtsolution do
|
5
|
+
before :each do
|
6
|
+
@valid_data = <<-EOS
|
7
|
+
1980 12 7 17 37 9.70 36.0300 1.2300 10.0 0.0 0.0
|
8
|
+
event name: 120780A
|
9
|
+
time shift: 1.7000
|
10
|
+
half duration: 2.0000
|
11
|
+
latitude: 36.0200
|
12
|
+
longitude: 0.9400
|
13
|
+
depth: 25.8000
|
14
|
+
Mrr: 1.747000e+24
|
15
|
+
Mtt: -2.197000e+24
|
16
|
+
Mpp: 4.500000e+23
|
17
|
+
Mrt: 7.430000e+23
|
18
|
+
Mrp: 1.376000e+24
|
19
|
+
Mtp: -1.491000e+24
|
20
|
+
EOS
|
21
|
+
|
22
|
+
@parsed_valid_data = {
|
23
|
+
hypocenter: {
|
24
|
+
data_source: '',
|
25
|
+
year: 1980,
|
26
|
+
month: 12,
|
27
|
+
day: 7,
|
28
|
+
hour: 17,
|
29
|
+
minute: 37,
|
30
|
+
second: 9.70,
|
31
|
+
latitude: 36.03,
|
32
|
+
longitude: 1.23,
|
33
|
+
depth: 10.0,
|
34
|
+
mb: 0.0,
|
35
|
+
ms: 0.0,
|
36
|
+
region_name: ''
|
37
|
+
},
|
38
|
+
event_name: '120780A',
|
39
|
+
centroid: {
|
40
|
+
time_shift: 1.7,
|
41
|
+
half_duration: 2.0,
|
42
|
+
latitude: 36.02,
|
43
|
+
longitude: 0.94,
|
44
|
+
depth: 25.8,
|
45
|
+
mrr: 1.747e+24,
|
46
|
+
mtt: -2.197e+24,
|
47
|
+
mpp: 4.5e+23,
|
48
|
+
mrt: 7.43e+23,
|
49
|
+
mrp: 1.376e+24,
|
50
|
+
mtp: -1.491e+24,
|
51
|
+
},
|
52
|
+
}
|
53
|
+
|
54
|
+
@wrong_data = <<-EOS
|
55
|
+
1980 12 7 17 37 9.70 36.0300 1.2300 10.0 0.0
|
56
|
+
event name: 120780A
|
57
|
+
time shift: 1.7000
|
58
|
+
half duration: 2.0000
|
59
|
+
latitude: 36.0200
|
60
|
+
longitude: 0.9400
|
61
|
+
depth: 25.8000
|
62
|
+
Mrr: 1.747000e+24
|
63
|
+
Mtt: -2.197000e+24
|
64
|
+
Mpp: 4.500000e+23
|
65
|
+
Mrt: 7.430000e+23
|
66
|
+
Mrp: 1.376000e+24
|
67
|
+
Mtp: -1.491000e+24
|
68
|
+
EOS
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '.parse' do
|
72
|
+
context 'normal case' do
|
73
|
+
it do
|
74
|
+
::SeisRuby::Data::Cmtsolution.parse(@valid_data).should == @parsed_valid_data
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'wrong case' do
|
79
|
+
it do
|
80
|
+
lambda{::SeisRuby::Data::Cmtsolution.parse(@wrong_data)}.should raise_error(::SeisRuby::Data::Cmtsolution::ParseError)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '.parse_list' do
|
86
|
+
context 'normal case' do
|
87
|
+
it do
|
88
|
+
::SeisRuby::Data::Cmtsolution.parse_list([@valid_data, @valid_data]).should == [@parsed_valid_data, @parsed_valid_data]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'wrong case' do
|
93
|
+
it do
|
94
|
+
lambda{::SeisRuby::Data::Cmtsolution.parse_list([@valid_data, @wrong_data])}.should raise_error(::SeisRuby::Data::Cmtsolution::ParseError)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ruby_patch'
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'seis_ruby'
|
5
|
+
|
6
|
+
describe ::SeisRuby::Io::GcmtCatalog do
|
7
|
+
describe '.scrape' do
|
8
|
+
context 'normal case' do
|
9
|
+
it do
|
10
|
+
::SeisRuby::Io::GcmtCatalog.scrape('http://www.globalcmt.org/cgi-bin/globalcmt-cgi-bin/CMT4/form?itype=ymd&yr=1976&mo=1&day=1&oyr=1976&omo=1&oday=1&jyr=1976&jday=1&ojyr=1&ojday=1&otype=nd&nday=400&lmw=0&umw=10&lms=0&ums=10&lmb=0&umb=10&llat=-90&ulat=90&llon=-180&ulon=180&lhd=0&uhd=1000<s=-9999&uts=9999&lpe1=0&upe1=90&lpe2=0&upe2=90&list=4').should == YAML.load_file(File.join(__DIR__, 'scrape.yaml'))
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'wrong case' do
|
14
|
+
it do
|
15
|
+
lambda{::SeisRuby::Io::GcmtCatalog.scrape('http://www.globalcmt.org/cgi-bin/globalcmt-cgi-bin/CMT4/form?itype=ymd&yr=1976&mo=1&day=1&oyr=1976&omo=1&oday=1&jyr=1976&jday=1&ojyr=1&ojday=1&otype=nd&nday=400&lmw=0&umw=10&lms=0&ums=10&lmb=0&umb=10&llat=-90&ulat=90&llon=-180&ulon=180&lhd=0&uhd=1000<s=-9999&uts=9999&lpe1=0&upe1=90&lpe2=0&upe2=90&list=3')}.should raise_error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|