geo_concerns 0.0.1 → 0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/README.md +6 -1
- data/app/models/concerns/geo_concerns/file_set/derivatives.rb +5 -5
- data/app/models/concerns/geo_concerns/image_file_behavior.rb +1 -1
- data/app/models/concerns/geo_concerns/raster_file_behavior.rb +1 -1
- data/app/models/concerns/geo_concerns/vector_file_behavior.rb +1 -1
- data/app/processors/geo_concerns/processors/base_geo_processor.rb +44 -34
- data/app/processors/geo_concerns/processors/gdal.rb +49 -0
- data/app/processors/geo_concerns/processors/ogr.rb +19 -0
- data/app/processors/geo_concerns/processors/raster/aig.rb +13 -17
- data/app/processors/geo_concerns/processors/raster/base.rb +15 -49
- data/app/processors/geo_concerns/processors/raster/dem.rb +14 -31
- data/app/processors/geo_concerns/processors/raster/info.rb +52 -0
- data/app/processors/geo_concerns/processors/raster/processor.rb +0 -1
- data/app/processors/geo_concerns/processors/vector/base.rb +16 -42
- data/app/processors/geo_concerns/processors/vector/processor.rb +0 -1
- data/app/processors/geo_concerns/processors/vector/shapefile.rb +2 -2
- data/app/processors/geo_concerns/processors/zip.rb +2 -4
- data/geo_concerns.gemspec +7 -8
- data/lib/geo_concerns/version.rb +1 -1
- data/spec/controllers/image_works_controller_spec.rb +16 -0
- data/spec/processors/geo_concerns/processors/base_geo_processor_spec.rb +29 -25
- data/spec/processors/geo_concerns/processors/gdal_spec.rb +59 -0
- data/spec/processors/geo_concerns/processors/ogr_spec.rb +36 -0
- data/spec/processors/geo_concerns/processors/raster/aig_spec.rb +12 -5
- data/spec/processors/geo_concerns/processors/raster/base_spec.rb +15 -47
- data/spec/processors/geo_concerns/processors/raster/dem_spec.rb +14 -10
- data/spec/processors/geo_concerns/processors/raster/info_spec.rb +35 -0
- data/spec/processors/geo_concerns/processors/vector/base_spec.rb +15 -28
- data/spec/processors/geo_concerns/processors/vector/shapefile_spec.rb +1 -1
- metadata +37 -42
@@ -0,0 +1,52 @@
|
|
1
|
+
module GeoConcerns
|
2
|
+
module Processors
|
3
|
+
module Raster
|
4
|
+
class Info
|
5
|
+
attr_accessor :doc
|
6
|
+
attr_writer :min_max, :size
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@doc = gdalinfo(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the min and max values for a raster.
|
13
|
+
# @return [String] computed min and max values
|
14
|
+
def min_max
|
15
|
+
@min_max ||= raster_min_max
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the raster size.
|
19
|
+
# @return [Array] raster size
|
20
|
+
def size
|
21
|
+
@size ||= raster_size
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Runs the gdalinfo command and returns the result as a string.
|
27
|
+
# @param path [String] path to raster file
|
28
|
+
# @return [String] output of gdalinfo
|
29
|
+
def gdalinfo(path)
|
30
|
+
stdout, _stderr, _status = Open3.capture3("gdalinfo -mm #{path}")
|
31
|
+
stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
# Given an output string from the gdalinfo command, returns
|
35
|
+
# a formatted string for the computed min and max values.
|
36
|
+
# @return [String] computed min and max values
|
37
|
+
def raster_min_max
|
38
|
+
match = %r{(?<=Computed Min/Max=).*?(?=\s)}.match(doc)
|
39
|
+
match ? match[0].tr(',', ' ') : ''
|
40
|
+
end
|
41
|
+
|
42
|
+
# Given an output string from the gdalinfo command, returns
|
43
|
+
# an array containing the raster width and height as strings.
|
44
|
+
# @return [String] raster size
|
45
|
+
def raster_size
|
46
|
+
match = /(?<=Size is ).*/.match(doc)
|
47
|
+
match ? match[0].tr(',', '') : ''
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -4,63 +4,37 @@ module GeoConcerns
|
|
4
4
|
class Base < Hydra::Derivatives::Processors::Processor
|
5
5
|
include Hydra::Derivatives::Processors::ShellBasedProcessor
|
6
6
|
include GeoConcerns::Processors::BaseGeoProcessor
|
7
|
+
include GeoConcerns::Processors::Ogr
|
8
|
+
include GeoConcerns::Processors::Gdal
|
7
9
|
include GeoConcerns::Processors::Zip
|
8
10
|
|
9
11
|
def self.encode(path, options, output_file)
|
10
12
|
case options[:label]
|
11
13
|
when :thumbnail
|
12
|
-
encode_vector(path,
|
14
|
+
encode_vector(path, output_file, options)
|
13
15
|
when :display_vector
|
14
|
-
reproject_vector(path,
|
16
|
+
reproject_vector(path, output_file, options)
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
File.unlink(tiff_path)
|
23
|
-
File.unlink("#{out_path}.aux.xml")
|
20
|
+
# Set of commands to run to encode the vector thumbnail.
|
21
|
+
# @return [Array] set of command name symbols
|
22
|
+
def self.encode_queue
|
23
|
+
[:rasterize, :convert]
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
FileUtils.rm_rf(shapefile_path)
|
26
|
+
# Set of commands to run to reproject the vector.
|
27
|
+
# @return [Array] set of command name symbols
|
28
|
+
def self.reproject_queue
|
29
|
+
[:reproject, :zip]
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
# @param in_path [String] file input path
|
37
|
-
# #param options [Hash] creation options
|
38
|
-
# @param out_path [String] processor output file path
|
39
|
-
# @return [String] command for rasterizing vector dataset
|
40
|
-
def self.rasterize(in_path, options, out_path)
|
41
|
-
"gdal_rasterize -q -burn 0 -init 255 -ot Byte -ts "\
|
42
|
-
"#{options[:output_size]} -of GTiff #{in_path} #{out_path}"
|
32
|
+
def self.encode_vector(in_path, out_path, options)
|
33
|
+
run_commands(in_path, out_path, encode_queue, options)
|
43
34
|
end
|
44
35
|
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
# @param in_path [String] file input path
|
49
|
-
# #param options [Hash] creation options
|
50
|
-
# @param out_path [String] processor output file path
|
51
|
-
# @return [String] command for reprojecting vector data
|
52
|
-
def self.reproject(in_path, options, out_path)
|
53
|
-
"env SHAPE_ENCODING= ogr2ogr -q -nln #{options[:basename]} "\
|
54
|
-
"-f 'ESRI Shapefile' -t_srs #{options[:output_srid]} '#{out_path}' '#{in_path}'"
|
55
|
-
end
|
56
|
-
|
57
|
-
# Returns a path to an intermediate shape file directory.
|
58
|
-
#
|
59
|
-
# @param path [String] file path to base temp path on
|
60
|
-
# @return [String] tempfile path
|
61
|
-
def self.intermediate_shapefile_path(path)
|
62
|
-
ext = File.extname(path)
|
63
|
-
"#{File.dirname(path)}/#{File.basename(path, ext)}/"
|
36
|
+
def self.reproject_vector(in_path, out_path, options)
|
37
|
+
run_commands(in_path, out_path, reproject_queue, options)
|
64
38
|
end
|
65
39
|
end
|
66
40
|
end
|
@@ -8,9 +8,9 @@ module GeoConcerns
|
|
8
8
|
unzip(path, output_file) do |zip_path|
|
9
9
|
case options[:label]
|
10
10
|
when :thumbnail
|
11
|
-
encode_vector(zip_path,
|
11
|
+
encode_vector(zip_path, output_file, options)
|
12
12
|
when :display_vector
|
13
|
-
reproject_vector(zip_path,
|
13
|
+
reproject_vector(zip_path, output_file, options)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -7,10 +7,9 @@ module GeoConcerns
|
|
7
7
|
# Unzips a file, invokes a block, and then deletes the unzipped file(s).
|
8
8
|
# Use to wrap processor methods for geo file formats that
|
9
9
|
# are zipped before uploading.
|
10
|
-
#
|
11
10
|
# @param in_path [String] file input path
|
12
11
|
# @param output_file [String] processor output file path
|
13
|
-
def self.unzip(in_path, output_file)
|
12
|
+
def self.unzip(in_path, output_file, _options = {})
|
14
13
|
basename = File.basename(output_file, File.extname(output_file))
|
15
14
|
zip_out_path = "#{File.dirname(output_file)}/#{basename}_out"
|
16
15
|
execute "unzip -qq -j -d \"#{zip_out_path}\" \"#{in_path}\""
|
@@ -19,10 +18,9 @@ module GeoConcerns
|
|
19
18
|
end
|
20
19
|
|
21
20
|
# Zips a file or directory.
|
22
|
-
#
|
23
21
|
# @param in_path [String] file input path
|
24
22
|
# @param output_file [String] output zip file
|
25
|
-
def self.zip(in_path, output_file)
|
23
|
+
def self.zip(in_path, output_file, _options = {})
|
26
24
|
execute "zip -j -qq -r \"#{output_file}\" \"#{in_path}\""
|
27
25
|
end
|
28
26
|
end
|
data/geo_concerns.gemspec
CHANGED
@@ -18,19 +18,18 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency '
|
22
|
-
spec.add_dependency '
|
23
|
-
spec.add_dependency 'leaflet-rails'
|
21
|
+
spec.add_dependency 'curation_concerns', '~> 0.14.0.pre4'
|
22
|
+
spec.add_dependency 'leaflet-rails', '~> 0.7'
|
24
23
|
|
25
24
|
spec.add_development_dependency 'sqlite3'
|
26
25
|
spec.add_development_dependency 'rspec-rails'
|
27
|
-
spec.add_development_dependency 'engine_cart'
|
28
|
-
spec.add_development_dependency 'solr_wrapper'
|
26
|
+
spec.add_development_dependency 'engine_cart', '~> 0.8'
|
27
|
+
spec.add_development_dependency 'solr_wrapper', '~> 0.10'
|
29
28
|
spec.add_development_dependency 'fcrepo_wrapper', '~> 0.1'
|
30
29
|
spec.add_development_dependency 'pry-byebug'
|
31
30
|
spec.add_development_dependency 'database_cleaner', '< 1.1.0'
|
32
|
-
spec.add_development_dependency 'rubocop'
|
33
|
-
spec.add_development_dependency 'rubocop-rspec'
|
31
|
+
spec.add_development_dependency 'rubocop', '~> 0.39'
|
32
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.4.1'
|
34
33
|
spec.add_development_dependency 'factory_girl'
|
35
|
-
spec.add_development_dependency 'capybara'
|
34
|
+
spec.add_development_dependency 'capybara', '~> 2.7'
|
36
35
|
end
|
data/lib/geo_concerns/version.rb
CHANGED
@@ -22,4 +22,20 @@ describe CurationConcerns::ImageWorksController, type: :controller do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
describe '#create' do
|
27
|
+
let(:user) { FactoryGirl.create(:admin) }
|
28
|
+
before do
|
29
|
+
sign_in user
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when create is successful' do
|
33
|
+
let(:work) { FactoryGirl.create(:image_work, user: user) }
|
34
|
+
it 'creates an image work' do
|
35
|
+
allow(controller).to receive(:curation_concern).and_return(work)
|
36
|
+
post :create, image_work: { title: ['a title'] }
|
37
|
+
expect(response).to redirect_to main_app.curation_concerns_image_work_path(work)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
25
41
|
end
|
@@ -4,6 +4,7 @@ describe GeoConcerns::Processors::BaseGeoProcessor do
|
|
4
4
|
before do
|
5
5
|
class TestProcessor
|
6
6
|
include GeoConcerns::Processors::BaseGeoProcessor
|
7
|
+
include GeoConcerns::Processors::Gdal
|
7
8
|
def directives
|
8
9
|
end
|
9
10
|
|
@@ -22,19 +23,38 @@ describe GeoConcerns::Processors::BaseGeoProcessor do
|
|
22
23
|
let(:directives) { { format: 'png', size: '200x400' } }
|
23
24
|
let(:output_file) { 'output/geo.png' }
|
24
25
|
let(:file_name) { 'files/geo.tif' }
|
25
|
-
let(:options) { {
|
26
|
+
let(:options) { { output_size: '150 150' } }
|
27
|
+
|
28
|
+
describe '#run_commands' do
|
29
|
+
let(:method_queue) { [:translate, :warp, :compress] }
|
30
|
+
it 'calls the methods in the queue and cleans up temp files' do
|
31
|
+
expect(subject.class).to receive(:translate)
|
32
|
+
expect(subject.class).to receive(:warp)
|
33
|
+
expect(subject.class).to receive(:compress)
|
34
|
+
expect(FileUtils).to receive(:rm_rf).twice
|
35
|
+
subject.class.run_commands(file_name, output_file, method_queue, options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#convert' do
|
40
|
+
let(:image) { double }
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
before do
|
43
|
+
allow(MiniMagick::Image).to receive(:open).and_return(image)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'transforms the image and saves it as a jpeg' do
|
47
|
+
expect(image).to receive(:format).with('jpg')
|
48
|
+
expect(image).to receive(:combine_options)
|
49
|
+
expect(image).to receive(:write).with(output_file)
|
50
|
+
subject.class.convert(file_name, output_file, options)
|
31
51
|
end
|
32
52
|
end
|
33
53
|
|
34
|
-
describe '#
|
54
|
+
describe '#temp_path' do
|
35
55
|
it 'returns a path to a temporary file based on the input file' do
|
36
|
-
expect(subject.class.
|
37
|
-
.to include('
|
56
|
+
expect(subject.class.temp_path(output_file))
|
57
|
+
.to include('geo')
|
38
58
|
end
|
39
59
|
end
|
40
60
|
|
@@ -53,21 +73,6 @@ describe GeoConcerns::Processors::BaseGeoProcessor do
|
|
53
73
|
end
|
54
74
|
end
|
55
75
|
|
56
|
-
describe '#output_format' do
|
57
|
-
context 'when given jpg as a format' do
|
58
|
-
let(:directives) { { format: 'jpg' } }
|
59
|
-
it 'returns JPEG' do
|
60
|
-
expect(subject.output_format).to eq('JPEG')
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context 'when given png as a format' do
|
65
|
-
it 'returns PNG' do
|
66
|
-
expect(subject.output_format).to eq('PNG')
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
76
|
describe '#output_size' do
|
72
77
|
context 'when given a size string with an x' do
|
73
78
|
it 'returns a size string with a space instead' do
|
@@ -99,8 +104,7 @@ describe GeoConcerns::Processors::BaseGeoProcessor do
|
|
99
104
|
|
100
105
|
describe '#options_for' do
|
101
106
|
it 'returns a hash that includes output size and format' do
|
102
|
-
expect(subject.options_for("a")).to include(:
|
103
|
-
:output_size,
|
107
|
+
expect(subject.options_for("a")).to include(:output_size,
|
104
108
|
:label,
|
105
109
|
:output_srid,
|
106
110
|
:basename)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GeoConcerns::Processors::BaseGeoProcessor do
|
4
|
+
before do
|
5
|
+
class TestProcessor
|
6
|
+
include Hydra::Derivatives::Processors::ShellBasedProcessor
|
7
|
+
include GeoConcerns::Processors::Gdal
|
8
|
+
def directives
|
9
|
+
end
|
10
|
+
|
11
|
+
def source_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
allow(subject).to receive(:directives).and_return(directives)
|
16
|
+
allow(subject).to receive(:source_path).and_return(file_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
after { Object.send(:remove_const, :TestProcessor) }
|
20
|
+
|
21
|
+
subject { TestProcessor.new }
|
22
|
+
|
23
|
+
let(:directives) { { format: 'png', size: '200x400' } }
|
24
|
+
let(:output_file) { 'output/geo.png' }
|
25
|
+
let(:file_name) { 'files/geo.tif' }
|
26
|
+
let(:options) { { output_size: '150 150', output_srid: 'EPSG:4326' } }
|
27
|
+
|
28
|
+
describe '#translate' do
|
29
|
+
it 'executes a gdal_translate command' do
|
30
|
+
command = "gdal_translate -q -ot Byte -of GTiff \"files/geo.tif\" output/geo.png"
|
31
|
+
expect(subject.class).to receive(:execute).with command
|
32
|
+
subject.class.translate(file_name, output_file, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#warp' do
|
37
|
+
it 'executes a reproject command' do
|
38
|
+
command = "gdalwarp -q -r bilinear -t_srs EPSG:4326 files/geo.tif output/geo.png -co 'COMPRESS=NONE'"
|
39
|
+
expect(subject.class).to receive(:execute).with command
|
40
|
+
subject.class.warp(file_name, output_file, options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#compress' do
|
45
|
+
it 'returns a gdal_translate command with a compress option' do
|
46
|
+
command = "gdal_translate -q -ot Byte -a_srs EPSG:4326 files/geo.tif output/geo.png -co 'COMPRESS=LZW'"
|
47
|
+
expect(subject.class).to receive(:execute).with command
|
48
|
+
subject.class.compress(file_name, output_file, options)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#rasterize' do
|
53
|
+
it 'executes a rasterize command' do
|
54
|
+
command = "gdal_rasterize -q -burn 0 -init 255 -ot Byte -ts 150 150 -of GTiff files/geo.tif output/geo.png"
|
55
|
+
expect(subject.class).to receive(:execute).with command
|
56
|
+
subject.class.rasterize(file_name, output_file, options)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GeoConcerns::Processors::BaseGeoProcessor do
|
4
|
+
before do
|
5
|
+
class TestProcessor
|
6
|
+
include Hydra::Derivatives::Processors::ShellBasedProcessor
|
7
|
+
include GeoConcerns::Processors::Ogr
|
8
|
+
def directives
|
9
|
+
end
|
10
|
+
|
11
|
+
def source_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
allow(subject).to receive(:directives).and_return(directives)
|
16
|
+
allow(subject).to receive(:source_path).and_return(file_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
after { Object.send(:remove_const, :TestProcessor) }
|
20
|
+
|
21
|
+
subject { TestProcessor.new }
|
22
|
+
|
23
|
+
let(:directives) { { format: 'png', size: '200x400' } }
|
24
|
+
let(:output_file) { 'output/geo.png' }
|
25
|
+
let(:file_name) { 'files/geo.zip' }
|
26
|
+
let(:options) { { output_size: '150 150', output_srid: 'EPSG:4326' } }
|
27
|
+
|
28
|
+
describe '#reproject' do
|
29
|
+
it 'executes a reproject command' do
|
30
|
+
command = "env SHAPE_ENCODING= ogr2ogr -q -nln -f 'ESRI Shapefile' "\
|
31
|
+
"-t_srs EPSG:4326 'output/geo.png' 'files/geo.zip'"
|
32
|
+
expect(subject.class).to receive(:execute).with command
|
33
|
+
subject.class.reproject(file_name, output_file, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -3,8 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe GeoConcerns::Processors::Raster::Aig do
|
4
4
|
let(:output_file) { 'output/geo.png' }
|
5
5
|
let(:file_name) { 'files/aig.zip' }
|
6
|
-
let(:options) { {
|
7
|
-
output_size: '150 150',
|
6
|
+
let(:options) { { output_size: '150 150',
|
8
7
|
min_max: '2.054 11.717',
|
9
8
|
label: :thumbnail }
|
10
9
|
}
|
@@ -12,9 +11,17 @@ describe GeoConcerns::Processors::Raster::Aig do
|
|
12
11
|
subject { described_class.new(file_name, {}) }
|
13
12
|
|
14
13
|
describe '#translate' do
|
15
|
-
it '
|
16
|
-
|
17
|
-
|
14
|
+
it 'executes a gdal_translate command with scaling' do
|
15
|
+
command = "gdal_translate -scale 2.054 11.717 255 0 -q -ot Byte -of "\
|
16
|
+
"GTiff \"files/aig.zip\" output/geo.png"
|
17
|
+
expect(subject.class).to receive(:execute).with command
|
18
|
+
subject.class.translate(file_name, output_file, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#reproject_queue' do
|
23
|
+
it 'returns an array of command name symbols' do
|
24
|
+
expect(subject.class.reproject_queue).to include :warp
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|