stac 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +18 -0
- data/GETTING_STARTED.md +384 -0
- data/Gemfile.lock +48 -37
- data/README.md +16 -57
- data/Rakefile +62 -4
- data/Steepfile +2 -0
- data/lib/stac/asset.rb +7 -1
- data/lib/stac/catalog.rb +81 -9
- data/lib/stac/collection.rb +43 -9
- data/lib/stac/common_metadata.rb +162 -0
- data/lib/stac/errors.rb +2 -5
- data/lib/stac/extension.rb +34 -0
- data/lib/stac/extensions/electro_optical.rb +67 -0
- data/lib/stac/extensions/projection.rb +42 -0
- data/lib/stac/extensions/scientific_citation.rb +84 -0
- data/lib/stac/extensions/view_geometry.rb +38 -0
- data/lib/stac/extent.rb +39 -31
- data/lib/stac/file_writer.rb +31 -0
- data/lib/stac/hash_like.rb +74 -0
- data/lib/stac/item.rb +58 -22
- data/lib/stac/link.rb +50 -14
- data/lib/stac/object_resolver.rb +14 -20
- data/lib/stac/properties.rb +6 -1
- data/lib/stac/provider.rb +5 -1
- data/lib/stac/{default_http_client.rb → simple_http_client.rb} +9 -4
- data/lib/stac/stac_object.rb +142 -31
- data/lib/stac/version.rb +1 -1
- data/lib/stac.rb +18 -2
- data/sig/stac/asset.rbs +3 -3
- data/sig/stac/catalog.rbs +29 -5
- data/sig/stac/collection.rbs +13 -5
- data/sig/stac/common_metadata.rbs +34 -0
- data/sig/stac/errors.rbs +1 -4
- data/sig/stac/extension.rbs +12 -0
- data/sig/stac/extensions/electro_optical.rbs +40 -0
- data/sig/stac/extensions/projection.rbs +32 -0
- data/sig/stac/extensions/scientific_citation.rbs +38 -0
- data/sig/stac/extensions/view_geometry.rbs +22 -0
- data/sig/stac/extent.rbs +13 -16
- data/sig/stac/file_writer.rbs +13 -0
- data/sig/stac/hash_like.rbs +13 -0
- data/sig/stac/item.rbs +17 -7
- data/sig/stac/link.rbs +21 -12
- data/sig/stac/object_resolver.rbs +5 -9
- data/sig/stac/properties.rbs +3 -3
- data/sig/stac/provider.rbs +2 -3
- data/sig/stac/{default_http_client.rbs → simple_http_client.rbs} +5 -2
- data/sig/stac/stac_object.rbs +34 -11
- data/sig/stac.rbs +7 -1
- data/stac.gemspec +1 -1
- metadata +26 -9
data/Rakefile
CHANGED
@@ -1,19 +1,77 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
|
-
|
5
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
require 'rdoc/task'
|
7
|
+
|
6
8
|
RSpec::Core::RakeTask.new(:spec)
|
7
9
|
|
8
|
-
require 'rubocop/rake_task'
|
9
10
|
RuboCop::RakeTask.new
|
10
11
|
|
11
12
|
task default: %i[spec rubocop]
|
12
13
|
|
13
|
-
require 'rdoc/task'
|
14
14
|
RDoc::Task.new do |rdoc|
|
15
15
|
rdoc.rdoc_dir = 'doc'
|
16
16
|
rdoc.title = 'stac-ruby API docs'
|
17
|
-
rdoc.rdoc_files.include('README.md', 'CHANGELOG.md', 'lib/**/*.rb')
|
17
|
+
rdoc.rdoc_files.include('README.md', 'CHANGELOG.md', 'GETTING_STARTED.md', 'lib/**/*.rb')
|
18
18
|
rdoc.main = 'README.md'
|
19
19
|
end
|
20
|
+
|
21
|
+
namespace :fixture do
|
22
|
+
desc 'Setup spec/fixtures'
|
23
|
+
task setup: %w[
|
24
|
+
spec/fixtures/stac-spec
|
25
|
+
spec/fixtures/eo/item.json
|
26
|
+
spec/fixtures/projection/item.json
|
27
|
+
spec/fixtures/scientific/item.json
|
28
|
+
spec/fixtures/scientific/collection.json
|
29
|
+
spec/fixtures/scientific/collection-assets.json
|
30
|
+
spec/fixtures/view/item.json
|
31
|
+
]
|
32
|
+
|
33
|
+
desc 'Remove spec/fixtures'
|
34
|
+
task :clean do
|
35
|
+
rm_r 'spec/fixtures'
|
36
|
+
end
|
37
|
+
|
38
|
+
directory 'spec/fixtures/stac-spec'
|
39
|
+
|
40
|
+
file 'spec/fixtures/stac-spec' do |t|
|
41
|
+
cp_r 'stac-spec/examples/.', t.name
|
42
|
+
end
|
43
|
+
|
44
|
+
directory 'spec/fixtures/eo'
|
45
|
+
|
46
|
+
file 'spec/fixtures/eo/item.json' => 'spec/fixtures/eo' do |t|
|
47
|
+
sh "curl https://raw.githubusercontent.com/stac-extensions/eo/v1.0.0/examples/item.json -o #{t.name} -sS"
|
48
|
+
end
|
49
|
+
|
50
|
+
directory 'spec/fixtures/projection'
|
51
|
+
|
52
|
+
file 'spec/fixtures/projection/item.json' => 'spec/fixtures/projection' do |t|
|
53
|
+
sh "curl https://raw.githubusercontent.com/stac-extensions/projection/v1.0.0/examples/item.json -o #{t.name} -sS"
|
54
|
+
end
|
55
|
+
|
56
|
+
directory 'spec/fixtures/scientific'
|
57
|
+
|
58
|
+
file 'spec/fixtures/scientific/item.json' => 'spec/fixtures/scientific' do |t|
|
59
|
+
sh "curl https://raw.githubusercontent.com/stac-extensions/scientific/v1.0.0/examples/item.json -o #{t.name} -sS"
|
60
|
+
end
|
61
|
+
|
62
|
+
file 'spec/fixtures/scientific/collection.json' => 'spec/fixtures/scientific' do |t|
|
63
|
+
sh 'curl https://raw.githubusercontent.com/stac-extensions/scientific/v1.0.0/examples/collection.json ' \
|
64
|
+
"-o #{t.name} -sS"
|
65
|
+
end
|
66
|
+
|
67
|
+
file 'spec/fixtures/scientific/collection-assets.json' => 'spec/fixtures/scientific' do |t|
|
68
|
+
sh 'curl https://raw.githubusercontent.com/stac-extensions/scientific/v1.0.0/examples/collection-assets.json ' \
|
69
|
+
"-o #{t.name} -sS"
|
70
|
+
end
|
71
|
+
|
72
|
+
directory 'spec/fixtures/view'
|
73
|
+
|
74
|
+
file 'spec/fixtures/view/item.json' => 'spec/fixtures/view' do |t|
|
75
|
+
sh "curl https://raw.githubusercontent.com/stac-extensions/view/v1.0.0/examples/item.json -o #{t.name} -sS"
|
76
|
+
end
|
77
|
+
end
|
data/Steepfile
CHANGED
@@ -15,6 +15,8 @@ target :lib do
|
|
15
15
|
hash[D::Ruby::InsufficientKeywordArguments] = :hint
|
16
16
|
hash[D::Ruby::MethodBodyTypeMismatch] = :information
|
17
17
|
hash[D::Ruby::MethodDefinitionMissing] = nil # To supress noisy VS Code extension message.
|
18
|
+
hash[D::Ruby::NoMethod] = :information
|
19
|
+
hash[D::Ruby::UnknownConstant] = :information
|
18
20
|
hash[D::Ruby::UnsupportedSyntax] = :hint
|
19
21
|
end
|
20
22
|
end
|
data/lib/stac/asset.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'common_metadata'
|
4
|
+
require_relative 'hash_like'
|
5
|
+
|
3
6
|
module STAC
|
4
7
|
# Represents \STAC asset object, which contains a link to data associated with an Item or Collection that can be
|
5
8
|
# downloaded or streamed.
|
6
9
|
class Asset
|
10
|
+
include HashLike
|
11
|
+
include CommonMetadata
|
12
|
+
|
7
13
|
class << self
|
8
14
|
# Deserializes an Asset from a Hash.
|
9
15
|
def from_hash(hash)
|
@@ -11,7 +17,7 @@ module STAC
|
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
14
|
-
attr_accessor :href, :title, :description, :type, :roles
|
20
|
+
attr_accessor :href, :title, :description, :type, :roles
|
15
21
|
|
16
22
|
def initialize(href:, title: nil, description: nil, type: nil, roles: nil, **extra)
|
17
23
|
@href = href
|
data/lib/stac/catalog.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'pathname'
|
3
4
|
require_relative 'errors'
|
4
5
|
require_relative 'stac_object'
|
5
6
|
|
@@ -8,20 +9,33 @@ module STAC
|
|
8
9
|
#
|
9
10
|
# \STAC \Catalog Specification: https://github.com/radiantearth/stac-spec/tree/master/catalog-spec
|
10
11
|
class Catalog < STAC::STACObject
|
11
|
-
|
12
|
+
@type = 'Catalog'
|
12
13
|
|
13
|
-
|
14
|
+
class << self
|
15
|
+
def root(id:, description:, href:, links: [], title: nil, stac_extensions: [], **extra)
|
16
|
+
catalog = new(
|
17
|
+
id: id, description: description, links: links, title: title, stac_extensions: stac_extensions, **extra,
|
18
|
+
)
|
19
|
+
catalog.self_href = href
|
20
|
+
catalog.root = catalog
|
21
|
+
catalog
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :id, :description, :title
|
14
26
|
|
15
|
-
def initialize(id:, description:, links
|
16
|
-
|
27
|
+
def initialize(id:, description:, links: [], title: nil, stac_extensions: [], **extra)
|
28
|
+
@id = id
|
17
29
|
@description = description
|
18
30
|
@title = title
|
31
|
+
super(links: links, stac_extensions: stac_extensions, **extra)
|
19
32
|
end
|
20
33
|
|
21
34
|
# Serializes self to a Hash.
|
22
35
|
def to_h
|
23
36
|
super.merge(
|
24
37
|
{
|
38
|
+
'id' => id,
|
25
39
|
'title' => title,
|
26
40
|
'description' => description,
|
27
41
|
}.compact,
|
@@ -30,7 +44,11 @@ module STAC
|
|
30
44
|
|
31
45
|
# Returns catalog/collection objects from rel="child" links of this catalog.
|
32
46
|
def children
|
33
|
-
|
47
|
+
child_links.lazy.map(&:target)
|
48
|
+
end
|
49
|
+
|
50
|
+
def all_children # :nodoc:
|
51
|
+
children.chain(children.flat_map(&:all_children)).lazy
|
34
52
|
end
|
35
53
|
|
36
54
|
# Filters only collections from #children.
|
@@ -38,17 +56,24 @@ module STAC
|
|
38
56
|
children.select { |child| child.type == 'Collection' }
|
39
57
|
end
|
40
58
|
|
59
|
+
# Returns all collections from this catalog and its child catalogs/collections recursively.
|
60
|
+
def all_collections
|
61
|
+
# The last `.lazy` is not necessary with Ruby 3.1.
|
62
|
+
# But with Ruby 3.0, it is necessary because Enumerator::Lazy#chain returns Enumerator::Chain
|
63
|
+
# and RBS type check fails.
|
64
|
+
collections.chain(children.flat_map(&:all_collections)).lazy
|
65
|
+
end
|
66
|
+
|
41
67
|
# Returns the child catalog/collection with the given ID if it exists.
|
42
68
|
#
|
43
69
|
# With option `recusive: true`, it will traverse all child catalogs/collections recursively.
|
44
70
|
def find_child(id, recursive: false)
|
45
|
-
|
46
|
-
targets.find { |child| child.id == id }
|
71
|
+
(recursive ? all_children : children).find { |child| child.id == id }
|
47
72
|
end
|
48
73
|
|
49
74
|
# Returns item objects from rel="item" links of this catalog.
|
50
75
|
def items
|
51
|
-
|
76
|
+
item_links.lazy.map(&:target)
|
52
77
|
end
|
53
78
|
|
54
79
|
# Returns all items from this catalog and its child catalogs/collections recursively.
|
@@ -56,7 +81,7 @@ module STAC
|
|
56
81
|
# The last `.lazy` is not necessary with Ruby 3.1.
|
57
82
|
# But with Ruby 3.0, it is necessary because Enumerator::Lazy#chain returns Enumerator::Chain
|
58
83
|
# and RBS type check fails.
|
59
|
-
items.chain(children.flat_map(&:
|
84
|
+
items.chain(children.flat_map(&:all_items)).lazy
|
60
85
|
end
|
61
86
|
|
62
87
|
# Returns the item with the given ID if it exists.
|
@@ -65,5 +90,52 @@ module STAC
|
|
65
90
|
def find_item(id, recursive: false)
|
66
91
|
(recursive ? all_items : items).find { |item| item.id == id }
|
67
92
|
end
|
93
|
+
|
94
|
+
# Adds a rel="child" link to self and adds "self", "root", and "parent" links to the child catalog.
|
95
|
+
def add_child(catalog, href: "#{catalog.id}/#{catalog.type.downcase}.json", title: catalog.title)
|
96
|
+
if (base = self_href)
|
97
|
+
catalog.self_href = Pathname(base).dirname.join(href).to_s
|
98
|
+
end
|
99
|
+
catalog.root = root
|
100
|
+
catalog.parent = self
|
101
|
+
add_link(catalog, rel: 'child', type: 'application/json', title: title)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Adds a rel="item" link to self and adds "self", "root", and "parent" links to the given item.
|
105
|
+
def add_item(item, href: "#{item.id}.json", title: item.properties.title)
|
106
|
+
if (base = self_href)
|
107
|
+
item.self_href = Pathname(base).dirname.join(href).to_s
|
108
|
+
end
|
109
|
+
item.root = root
|
110
|
+
item.parent = self
|
111
|
+
add_link(item, rel: 'item', type: 'application/geo+json', title: title)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Exports this catalog and all its children and items to the specified dir or each self href.
|
115
|
+
def export(dest_dir = nil, writer: FileWriter.new)
|
116
|
+
dest_pathname = Pathname(dest_dir) if dest_dir
|
117
|
+
self_dest = dest_pathname.join(File.basename(self_href!)).to_s if dest_pathname
|
118
|
+
save(self_dest, writer: writer)
|
119
|
+
|
120
|
+
item_links.select(&:resolved?).each do |item_link|
|
121
|
+
item_dest = dest_pathname.join(item_link.relative_href!).to_s if dest_pathname
|
122
|
+
item_link.target.save(item_dest, writer: writer)
|
123
|
+
end
|
124
|
+
|
125
|
+
child_links.select(&:resolved?).each do |child_link|
|
126
|
+
child_dest_dir = dest_pathname.join(child_link.relative_href!).dirname.to_s if dest_pathname
|
127
|
+
child_link.target.export(child_dest_dir, writer: writer)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def child_links
|
134
|
+
links.select { |link| link.rel == 'child' }
|
135
|
+
end
|
136
|
+
|
137
|
+
def item_links
|
138
|
+
links.select { |link| link.rel == 'item' }
|
139
|
+
end
|
68
140
|
end
|
69
141
|
end
|
data/lib/stac/collection.rb
CHANGED
@@ -10,43 +10,46 @@ module STAC
|
|
10
10
|
#
|
11
11
|
# \STAC \Collection Specification: https://github.com/radiantearth/stac-spec/tree/master/collection-spec
|
12
12
|
class Collection < Catalog
|
13
|
-
|
13
|
+
@type = 'Collection'
|
14
14
|
|
15
15
|
class << self
|
16
16
|
def from_hash(hash)
|
17
|
-
h = hash.
|
18
|
-
h[
|
19
|
-
h[
|
20
|
-
h[
|
17
|
+
h = hash.transform_keys(&:to_sym)
|
18
|
+
h[:extent] = Extent.from_hash(h.fetch(:extent))
|
19
|
+
h[:providers] = h[:providers]&.map { |provider| Provider.from_hash(provider) }
|
20
|
+
h[:summaries] = h[:summaries]&.transform_keys(&:to_s)
|
21
|
+
h[:assets] = h[:assets]&.to_h { |k, v| [k.to_s, Asset.from_hash(v)] }
|
21
22
|
super(h)
|
22
23
|
rescue KeyError => e
|
23
24
|
raise ArgumentError, "required field not found: #{e.key}"
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
attr_accessor :license, :extent, :keywords, :providers, :summaries
|
28
|
+
attr_accessor :license, :extent, :keywords, :providers, :summaries
|
29
|
+
|
30
|
+
attr_reader :assets
|
28
31
|
|
29
32
|
def initialize(
|
30
33
|
id:,
|
31
34
|
description:,
|
32
|
-
links:,
|
33
35
|
license:,
|
34
36
|
extent:,
|
37
|
+
links: [],
|
35
38
|
title: nil,
|
36
39
|
keywords: nil,
|
37
40
|
providers: nil,
|
38
41
|
summaries: nil,
|
39
42
|
assets: nil,
|
40
|
-
stac_extensions:
|
43
|
+
stac_extensions: [],
|
41
44
|
**extra
|
42
45
|
)
|
43
|
-
super(id: id, description: description, links: links, title: title, stac_extensions: stac_extensions, **extra)
|
44
46
|
@license = license
|
45
47
|
@extent = extent
|
46
48
|
@keywords = keywords
|
47
49
|
@providers = providers
|
48
50
|
@summaries = summaries
|
49
51
|
@assets = assets
|
52
|
+
super(id: id, description: description, links: links, title: title, stac_extensions: stac_extensions, **extra)
|
50
53
|
end
|
51
54
|
|
52
55
|
# Serializes self to a Hash.
|
@@ -62,5 +65,36 @@ module STAC
|
|
62
65
|
}.compact,
|
63
66
|
)
|
64
67
|
end
|
68
|
+
|
69
|
+
# Adds an asset with the given key.
|
70
|
+
#
|
71
|
+
# When the item has extendable stac_extensions, make the asset extend the extension modules.
|
72
|
+
def add_asset(key:, href:, title: nil, description: nil, type: nil, roles: nil, **extra)
|
73
|
+
asset = Asset.new(href: href, title: title, description: description, type: type, roles: roles, **extra)
|
74
|
+
extensions.each do |extension|
|
75
|
+
asset.extend(extension::Asset) if extension.const_defined?(:Asset)
|
76
|
+
end
|
77
|
+
if assets
|
78
|
+
assets[key] = asset
|
79
|
+
else
|
80
|
+
@assets = { key => asset }
|
81
|
+
end
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# Adds a rel="item" link to self and adds "self", "root", "parent", and "collection" links to the given item.
|
86
|
+
def add_item(item, href: "#{item.id}.json", title: item.properties.title)
|
87
|
+
super
|
88
|
+
item.collection = self
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def apply_extension!(extension)
|
95
|
+
super
|
96
|
+
extend(extension::Collection) if extension.const_defined?(:Collection)
|
97
|
+
assets&.each_value { |asset| asset.extend(extension::Asset) } if extension.const_defined?(:Asset)
|
98
|
+
end
|
65
99
|
end
|
66
100
|
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module STAC
|
6
|
+
# Provides read/write methods for \STAC Common Metadata.
|
7
|
+
#
|
8
|
+
# These methods are shorthand accessors of #extra Hash.
|
9
|
+
# Asset and \Item Properties include this module.
|
10
|
+
#
|
11
|
+
# Specification: https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md
|
12
|
+
module CommonMetadata
|
13
|
+
attr_reader :extra
|
14
|
+
|
15
|
+
def title
|
16
|
+
extra['title']
|
17
|
+
end
|
18
|
+
|
19
|
+
def title=(str)
|
20
|
+
extra['title'] = str
|
21
|
+
end
|
22
|
+
|
23
|
+
def description
|
24
|
+
extra['description']
|
25
|
+
end
|
26
|
+
|
27
|
+
def description=(str)
|
28
|
+
extra['description'] = str
|
29
|
+
end
|
30
|
+
|
31
|
+
def created
|
32
|
+
if (str = extra['created'])
|
33
|
+
Time.iso8601(str)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def created=(time)
|
38
|
+
extra['created'] = case time
|
39
|
+
when Time
|
40
|
+
time.iso8601
|
41
|
+
else
|
42
|
+
time
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def updated
|
47
|
+
if (str = extra['updated'])
|
48
|
+
Time.iso8601(str)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def updated=(time)
|
53
|
+
extra['updated'] = case time
|
54
|
+
when Time
|
55
|
+
time.iso8601
|
56
|
+
else
|
57
|
+
time
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def start_datetime
|
62
|
+
if (str = extra['start_datetime'])
|
63
|
+
Time.iso8601(str)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def start_datetime=(time)
|
68
|
+
extra['start_datetime'] = case time
|
69
|
+
when Time
|
70
|
+
time.iso8601
|
71
|
+
else
|
72
|
+
time
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def end_datetime
|
77
|
+
if (str = extra['end_datetime'])
|
78
|
+
Time.iso8601(str)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def end_datetime=(time)
|
83
|
+
extra['end_datetime'] = case time
|
84
|
+
when Time
|
85
|
+
time.iso8601
|
86
|
+
else
|
87
|
+
time
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a range from #start_datetime to #end_datetime.
|
92
|
+
def datetime_range
|
93
|
+
if (start = start_datetime) && (last = end_datetime)
|
94
|
+
start..last
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Sets #start_datetime and #end_datetime by the given range.
|
99
|
+
def datetime_range=(time_range)
|
100
|
+
self.start_datetime = time_range.begin
|
101
|
+
self.end_datetime = time_range.end
|
102
|
+
end
|
103
|
+
|
104
|
+
def license
|
105
|
+
extra['license']
|
106
|
+
end
|
107
|
+
|
108
|
+
def license=(str)
|
109
|
+
extra['license'] = str
|
110
|
+
end
|
111
|
+
|
112
|
+
def providers
|
113
|
+
extra.fetch('providers', []).map do |provider_hash|
|
114
|
+
Provider.from_hash(provider_hash)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def providers=(arr)
|
119
|
+
extra['providers'] = arr.map(&:to_h)
|
120
|
+
end
|
121
|
+
|
122
|
+
def platform
|
123
|
+
extra['platform']
|
124
|
+
end
|
125
|
+
|
126
|
+
def platform=(str)
|
127
|
+
extra['platform'] = str
|
128
|
+
end
|
129
|
+
|
130
|
+
def instruments
|
131
|
+
extra['instruments']
|
132
|
+
end
|
133
|
+
|
134
|
+
def instruments=(arr)
|
135
|
+
extra['instruments'] = arr
|
136
|
+
end
|
137
|
+
|
138
|
+
def constellation
|
139
|
+
extra['constellation']
|
140
|
+
end
|
141
|
+
|
142
|
+
def constellation=(str)
|
143
|
+
extra['constellation'] = str
|
144
|
+
end
|
145
|
+
|
146
|
+
def mission
|
147
|
+
extra['mission']
|
148
|
+
end
|
149
|
+
|
150
|
+
def mission=(str)
|
151
|
+
extra['mission'] = str
|
152
|
+
end
|
153
|
+
|
154
|
+
def gsd
|
155
|
+
extra['gsd']
|
156
|
+
end
|
157
|
+
|
158
|
+
def gsd=(num)
|
159
|
+
extra['gsd'] = num
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/stac/errors.rb
CHANGED
@@ -7,9 +7,6 @@ module STAC
|
|
7
7
|
# Raised when unexpected "type" field was given.
|
8
8
|
class TypeError < Error; end
|
9
9
|
|
10
|
-
# Raised when URL with
|
11
|
-
class
|
12
|
-
|
13
|
-
# Raised when a HTTP request failed.
|
14
|
-
class HTTPError < Error; end
|
10
|
+
# Raised when URL with not supported scheme was given.
|
11
|
+
class NotSupportedURISchemeError < Error; end
|
15
12
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors'
|
4
|
+
|
5
|
+
module STAC
|
6
|
+
# Raised when an extension module does have identifier.
|
7
|
+
class ExtensionWithoutIdentifierError < Error; end
|
8
|
+
|
9
|
+
# \Extension modules must extend this module.
|
10
|
+
module Extension
|
11
|
+
# Returns extension id for `stac_extensions` field.
|
12
|
+
#
|
13
|
+
# When given an argument, sets the given value as its identifier.
|
14
|
+
def identifier(identifier = nil)
|
15
|
+
# @type self: Module
|
16
|
+
if identifier.nil?
|
17
|
+
@identifier or raise ExtensionWithoutIdentifierError, "extension module must be set identifier: #{name}"
|
18
|
+
else
|
19
|
+
@identifier = identifier
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns extendable \STAC Object classes.
|
24
|
+
#
|
25
|
+
# When given arguments, sets the given values as its scope.
|
26
|
+
def scope(*scope)
|
27
|
+
if scope.empty?
|
28
|
+
@scope ||= []
|
29
|
+
else
|
30
|
+
@scope = scope
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../extension'
|
4
|
+
require_relative '../item'
|
5
|
+
|
6
|
+
module STAC
|
7
|
+
module Extensions
|
8
|
+
# Utilities for Electro-Optical extension.
|
9
|
+
#
|
10
|
+
# Electro-Optical \Extension Specification: https://github.com/stac-extensions/eo/
|
11
|
+
module ElectroOptical
|
12
|
+
extend Extension
|
13
|
+
|
14
|
+
identifier 'https://stac-extensions.github.io/eo/v1.0.0/schema.json'
|
15
|
+
scope STAC::Item
|
16
|
+
|
17
|
+
module Properties # rubocop:disable Style/Documentation
|
18
|
+
attr_reader :extra
|
19
|
+
|
20
|
+
def eo_bands
|
21
|
+
extra.fetch('eo:bands', []).map { |band_hash| Band.new(band_hash) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def eo_bands=(bands)
|
25
|
+
extra['eo:bands'] = bands.map(&:to_h)
|
26
|
+
end
|
27
|
+
|
28
|
+
def eo_cloud_cover
|
29
|
+
extra['eo:cloud_cover']
|
30
|
+
end
|
31
|
+
|
32
|
+
def eo_cloud_cover=(cloud_cover)
|
33
|
+
extra['eo:cloud_cover'] = cloud_cover
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Asset
|
38
|
+
include Properties
|
39
|
+
end
|
40
|
+
|
41
|
+
# Represents \Band object of Electro-Optical extension.
|
42
|
+
class Band
|
43
|
+
attr_reader :raw_hash # :nodoc:
|
44
|
+
|
45
|
+
def initialize(raw_hash)
|
46
|
+
@raw_hash = raw_hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_h
|
50
|
+
raw_hash
|
51
|
+
end
|
52
|
+
|
53
|
+
%i[name common_name description center_wavelength full_width_half_max].each do |field|
|
54
|
+
define_method(field) do
|
55
|
+
# @type self: Band
|
56
|
+
raw_hash[field.to_s]
|
57
|
+
end
|
58
|
+
|
59
|
+
define_method("#{field}=") do |value|
|
60
|
+
# @type self: Band
|
61
|
+
raw_hash[field.to_s] = value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../extension'
|
4
|
+
require_relative '../item'
|
5
|
+
|
6
|
+
module STAC
|
7
|
+
module Extensions
|
8
|
+
# Utilities for \Projection extension.
|
9
|
+
#
|
10
|
+
# \Projection \Extension Specification: https://github.com/stac-extensions/projection/
|
11
|
+
module Projection
|
12
|
+
extend Extension
|
13
|
+
|
14
|
+
identifier 'https://stac-extensions.github.io/projection/v1.0.0/schema.json'
|
15
|
+
scope STAC::Item
|
16
|
+
|
17
|
+
module Properties # rubocop:disable Style/Documentation
|
18
|
+
attr_reader :extra
|
19
|
+
|
20
|
+
%w[
|
21
|
+
proj:epsg proj:wkt2 proj:projjson proj:geometry proj:bbox proj:centroid proj:shape proj:transform
|
22
|
+
].each do |field|
|
23
|
+
method_name = field.sub(':', '_')
|
24
|
+
|
25
|
+
define_method(method_name) do
|
26
|
+
# @type self: Properties
|
27
|
+
extra[field]
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method("#{method_name}=") do |value|
|
31
|
+
# @type self: Properties
|
32
|
+
extra[field] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Asset
|
38
|
+
include Properties
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|