stac 0.1.0 → 0.3.0
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.
- 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
|