grassgis 0.3.1 → 0.4.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/README.md +236 -88
- data/lib/grassgis/context.rb +112 -23
- data/lib/grassgis/error.rb +4 -0
- data/lib/grassgis/location.rb +53 -0
- data/lib/grassgis/mapset.rb +31 -0
- data/lib/grassgis/module.rb +1 -0
- data/lib/grassgis/version.rb +1 -1
- data/lib/grassgis.rb +3 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecfff7260f29f4ce2f8add71b7ddba2160855b38
|
4
|
+
data.tar.gz: 263eacdcc9a5abe048d75855c226c583add5a472
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8a33caff0aa903fe0e5e86676b345b57db4028d8e309de3e8ef360a303473056325abad6c2543d46c5381d12dae53b2481eb54d1825a62b5ba8e2cf5d7bf53e
|
7
|
+
data.tar.gz: 15598756b12558e632c200efbaf660fd3e030e17011d89335f57fb4b79b81b033b2c5b573d81c1af07d6a1289782499280ec889f28bb346c5a6501f9bec09ae1
|
data/README.md
CHANGED
@@ -5,6 +5,34 @@
|
|
5
5
|
|
6
6
|
Support for scripting GRASS with Ruby.
|
7
7
|
|
8
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
9
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
10
|
+
**Table of Contents**
|
11
|
+
|
12
|
+
- [Installation](#installation)
|
13
|
+
- [Usage](#usage)
|
14
|
+
- [Configuration](#configuration)
|
15
|
+
- [Running a GRASS Session](#running-a-grass-session)
|
16
|
+
- [Creating new locations and mapsets](#creating-new-locations-and-mapsets)
|
17
|
+
- [History](#history)
|
18
|
+
- [Options](#options)
|
19
|
+
- [Echo](#echo)
|
20
|
+
- [Errors](#errors)
|
21
|
+
- [Logging](#logging)
|
22
|
+
- [Technicalities](#technicalities)
|
23
|
+
- [Session scopes](#session-scopes)
|
24
|
+
- [Invalid commands](#invalid-commands)
|
25
|
+
- [Helper methods](#helper-methods)
|
26
|
+
- [Examples](#examples)
|
27
|
+
- [1. Map existence](#1-map-existence)
|
28
|
+
- [2. Information as Hashes](#2-information-as-hashes)
|
29
|
+
- [3. Average angle](#3-average-angle)
|
30
|
+
- [Roadmap](#roadmap)
|
31
|
+
- [GRASS cooking DSL](#grass-cooking-dsl)
|
32
|
+
- [Contributing](#contributing)
|
33
|
+
|
34
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
35
|
+
|
8
36
|
## Installation
|
9
37
|
|
10
38
|
Add this line to your application's Gemfile:
|
@@ -113,10 +141,212 @@ d.erase.run
|
|
113
141
|
g.list.run
|
114
142
|
```
|
115
143
|
|
144
|
+
### Creating new locations and mapsets
|
145
|
+
|
146
|
+
To create a new location and/or mapset, open a session to it
|
147
|
+
and use a `:create` parameter like this:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
options = configuration.merge(
|
151
|
+
location: 'new_location',
|
152
|
+
mapset: 'new_mapset',
|
153
|
+
create: {
|
154
|
+
epsg: 4326 # coordinate system for the new location
|
155
|
+
limits: [-5, 30, 5, 50], # optional E, S, W, N limits
|
156
|
+
res: 2 # optional resolution
|
157
|
+
}
|
158
|
+
)
|
159
|
+
GrassGis.session options do
|
160
|
+
g.region '-p'
|
161
|
+
puts output
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
Use `nil` or `PERMANENT` for the mapset to avoid creating a new mapset.
|
166
|
+
|
167
|
+
Existing locations or mapsets are not changed.
|
168
|
+
|
169
|
+
### History
|
170
|
+
|
171
|
+
The return value of a GRASS command invocation inside a session is
|
172
|
+
a `SysCmd::Command`
|
173
|
+
(see the [sys_cmd gem](https://github.com/jgoizueta/sys_cmd)).
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
GrassGis.session configuration do+
|
177
|
+
cmd = g.region '-p'
|
178
|
+
puts cmd.output # command output is kept in the Command object
|
179
|
+
puts cmd.status_value # 0 for success
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
You don't need to assign commands to variables as in the example
|
184
|
+
to access them, because they're all kept in an array accesible
|
185
|
+
through the `history` method of the session:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
GrassGis.session configuration do+
|
189
|
+
r.info 'slope'
|
190
|
+
g.region '-p'
|
191
|
+
puts history.size # 2
|
192
|
+
puts history[-1].output # output of g.region
|
193
|
+
puts history[-2].output # output of r.info
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
The last executed command (`history[-1]`) is also accessible through
|
198
|
+
the `last` method and its output through `output`:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
GrassGis.session configuration do+
|
202
|
+
r.info 'slope'
|
203
|
+
g.region '-p'
|
204
|
+
puts output # output of g.region (same as last.output)
|
205
|
+
puts last.status_value # result status of g.region
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
209
|
+
### Options
|
210
|
+
|
211
|
+
By default the commands executed in a session are echoed to standard output
|
212
|
+
(just the command, not its output) and error return status causes
|
213
|
+
an exception to be raised.
|
214
|
+
|
215
|
+
This behaviour can be changed with some options:
|
216
|
+
|
217
|
+
#### Echo
|
218
|
+
|
219
|
+
Pass `false` as the `:echo` option it you don't want to output
|
220
|
+
command names and `:output` if you want to output both
|
221
|
+
the command name and its output.
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
GrassGis.session configuration.merge(echo: false) do
|
225
|
+
# Command names not echoed now ...
|
226
|
+
end
|
227
|
+
|
228
|
+
GrassGis.session configuration.merge(echo: :output) do
|
229
|
+
# Command names and its output echoed ...
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
#### Errors
|
234
|
+
|
235
|
+
To avoid raising exceptions when commands return an error status you can pass
|
236
|
+
`:quiet` to the `:errors` option. In that case the `error?` method of the
|
237
|
+
session can be used to check if the previous messatge returned an error status;
|
238
|
+
`error_info` to get its error message and the status of the command
|
239
|
+
of the command can be obtained through the `last` command method.
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
GrassGis.session configuration.merge(errors: :quiet) do
|
243
|
+
r.surf.rst 'randpts', elev: 'rstdef', zcol: 'value'
|
244
|
+
if error?
|
245
|
+
puts "Last command didn't go well..."
|
246
|
+
puts "It returned the code: #{last.status_value}"
|
247
|
+
puts "Here's what it said about the problem:"
|
248
|
+
puts error_info
|
249
|
+
end
|
250
|
+
end
|
251
|
+
```
|
252
|
+
|
253
|
+
With the `:quiet` option errors during command execution are not raised,
|
254
|
+
but if a problem prevents the command from being executed (e.g. the
|
255
|
+
module does not exist) an exception is still generated. This exception
|
256
|
+
can be avoided too, with the `:silent` option, intended for tests and
|
257
|
+
debugging.
|
258
|
+
|
259
|
+
Passing the `:console` value to the `:errors` option is like `:quiet`,
|
260
|
+
with the additional effect of relaying the command standard error output
|
261
|
+
to the error output of the script.
|
262
|
+
|
263
|
+
#### Logging
|
264
|
+
|
265
|
+
With the `:log` option you can specify the name of a file
|
266
|
+
where to record the commands executed and its output.
|
267
|
+
|
268
|
+
### Technicalities
|
269
|
+
|
270
|
+
#### Session scopes
|
271
|
+
|
272
|
+
In a session block, the Ruby `self` object is altered to
|
273
|
+
refer to a `GrassGis::Context` object. That means that in addition
|
274
|
+
to the enclosing `self`, any instance variables of the enclosing
|
275
|
+
scope are not directly available. This may cause some surprises
|
276
|
+
but is easy to overcome.
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
@value = 10
|
280
|
+
GrassGis.session configuration do
|
281
|
+
puts @value # nil!
|
282
|
+
end
|
283
|
+
```
|
284
|
+
|
285
|
+
A possible workaround is to assign instance variables that we need
|
286
|
+
in the session to local variables:
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
@value = 10
|
290
|
+
value = @value
|
291
|
+
GrassGis.session configuration do
|
292
|
+
puts value # 10
|
293
|
+
end
|
294
|
+
```
|
295
|
+
|
296
|
+
To avoid defining these variables you can pass a `:locals` Hash
|
297
|
+
in the configuration to define values that you need to access
|
298
|
+
in the session (but you won't be able to assign to them, because
|
299
|
+
they're not local variables!)
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
@value = 10
|
303
|
+
|
304
|
+
GrassGis.session configuration.merge(locals: { value: @value }) do
|
305
|
+
puts value # 10
|
306
|
+
value = 11 # don't do this: you're creating a local in the session
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
310
|
+
A different approach is prevent the session block from using a special
|
311
|
+
`self` by defining a parameter to the block. This parameter will have
|
312
|
+
the value of a `GrassGis::Context` which you'll need to explicitly use
|
313
|
+
to execute any commands:
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
@value = 10
|
317
|
+
GrassGis.session configuration do |grass|
|
318
|
+
puts @value # 10
|
319
|
+
grass.g.region res: 10 # now you need to use the object to issue commans
|
320
|
+
end
|
321
|
+
```
|
322
|
+
|
323
|
+
#### Invalid commands
|
324
|
+
|
325
|
+
Currently the generation of GRASS commands inside a session is
|
326
|
+
implemented in a versy simple way which allows to generate any command
|
327
|
+
name even if it is invalid or does not exist. This has the advantage
|
328
|
+
of supporting any version of GRASS, but doesn't allow for early
|
329
|
+
detection of invalid commands (e.g. due to typos) or invalid command
|
330
|
+
parameters.
|
331
|
+
|
332
|
+
```ruby
|
333
|
+
GrassGis.session configuration do |grass|
|
334
|
+
g.regoin res: 10 # Oops (runtime error)
|
335
|
+
g.anything.goes.run # another runtime error
|
336
|
+
end
|
337
|
+
```
|
338
|
+
|
339
|
+
If the command generated does not exist a runtime `ENOENT` exception will
|
340
|
+
occur.
|
341
|
+
|
342
|
+
If the command exists, then if parameters are not valid, the command
|
343
|
+
will execute but will return an error status. This will be handled
|
344
|
+
as explaned above.
|
345
|
+
|
116
346
|
## Helper methods
|
117
347
|
|
118
348
|
When writing a non-trivial program you'll probably
|
119
|
-
find you want to define methods to avoid
|
349
|
+
find you want to define methods to avoid unnecessary repetition.
|
120
350
|
|
121
351
|
Let's see how you can call methdos from your session and be
|
122
352
|
able to execute GRASS commands from the method in the context of the session.
|
@@ -125,7 +355,7 @@ Inside a session, `self` refers to an object of class
|
|
125
355
|
`GrassGis::Context` which represents the current GRASS session.
|
126
356
|
|
127
357
|
You can invoke grass commands directly on this object, so, if you pass
|
128
|
-
this object
|
358
|
+
this object around you can use it to execute GRASS commands:
|
129
359
|
|
130
360
|
```ruby
|
131
361
|
def helper_method(grass)
|
@@ -195,8 +425,7 @@ GrassGis.session configuration do
|
|
195
425
|
end
|
196
426
|
```
|
197
427
|
|
198
|
-
|
199
|
-
### 2. Information as Hashes
|
428
|
+
#### 2. Information as Hashes
|
200
429
|
|
201
430
|
Following methods show how to obtain information about a raster map
|
202
431
|
and the current region as a Hash:
|
@@ -229,7 +458,7 @@ def region_res(grass)
|
|
229
458
|
end
|
230
459
|
```
|
231
460
|
|
232
|
-
|
461
|
+
#### 3. Average angle
|
233
462
|
|
234
463
|
Let's assume we have a raster map `aspect` which is
|
235
464
|
a direction angle (i.e. a cyclic value from 0 to 360).
|
@@ -291,91 +520,8 @@ GrassGis.session configuration do
|
|
291
520
|
end
|
292
521
|
```
|
293
522
|
|
294
|
-
### Options
|
295
|
-
|
296
|
-
TODO: Explain options for error handling, echoing, logging, ...
|
297
|
-
|
298
|
-
### Technicalities
|
299
|
-
|
300
|
-
#### Session scopes
|
301
|
-
|
302
|
-
In a session block, the Ruby `self` object is altered to
|
303
|
-
refer to a `GrassGis::Context` object. That means that in addition
|
304
|
-
to the enclosing `self`, any instance variables of the enclosing
|
305
|
-
scope are not directly available. This may cause some surprises
|
306
|
-
but is easy to overcome.
|
307
|
-
|
308
|
-
```ruby
|
309
|
-
@value = 10
|
310
|
-
GrassGis.session configuration do
|
311
|
-
puts @value # nil!
|
312
|
-
end
|
313
|
-
```
|
314
|
-
|
315
|
-
A possible workaround is to assign instance variables that we need
|
316
|
-
in the session to local variables:
|
317
|
-
|
318
|
-
```ruby
|
319
|
-
@value = 10
|
320
|
-
value = @value
|
321
|
-
GrassGis.session configuration do
|
322
|
-
puts value # 10
|
323
|
-
end
|
324
|
-
```
|
325
|
-
|
326
|
-
To avoid defining these variables you can pass a `:locals` Hash
|
327
|
-
in the configuration to define values that you need to access
|
328
|
-
in the session (but you won't be able to assign to them, because
|
329
|
-
they're not local variables!)
|
330
|
-
|
331
|
-
```ruby
|
332
|
-
@value = 10
|
333
|
-
|
334
|
-
GrassGis.session configuration.merge(locals: { value: @value }) do
|
335
|
-
puts value # 10
|
336
|
-
value = 11 # don't do this: you're creating a local in the session
|
337
|
-
end
|
338
|
-
```
|
339
|
-
|
340
|
-
A different approach is prevent the session block from using a special
|
341
|
-
`self` by defining a parameter to the block. This parameter will have
|
342
|
-
the value of a `GrassGis::Context` which you'll need to explicitly use
|
343
|
-
to execute any commands:
|
344
|
-
|
345
|
-
```ruby
|
346
|
-
@value = 10
|
347
|
-
GrassGis.session configuration do |grass|
|
348
|
-
puts @value # 10
|
349
|
-
grass.g.region res: 10 # now you need to use the object to issue commans
|
350
|
-
end
|
351
|
-
```
|
352
|
-
|
353
|
-
#### Invalid commands
|
354
|
-
|
355
|
-
Currently the generation of GRASS commands inside a session is
|
356
|
-
implemented in a versy simple way which allows to generate any command
|
357
|
-
name even if it is invalid or does not exist. This has the advantage
|
358
|
-
of supporting any version of GRASS, but doesn't allow for early
|
359
|
-
detection of invalid commands (e.g. due to typos) or invalid command
|
360
|
-
parameters.
|
361
|
-
|
362
|
-
```ruby
|
363
|
-
GrassGis.session configuration do |grass|
|
364
|
-
g.regoin res: 10 # Oops (runtime error)
|
365
|
-
g.anything.goes.run # another runtime error
|
366
|
-
end
|
367
|
-
```
|
368
|
-
|
369
|
-
If the command generated does not exist a runtime `ENOENT` exception will
|
370
|
-
occur.
|
371
|
-
|
372
|
-
If the command exists, then if parameters are not valid, the command
|
373
|
-
will execute but will return an error status. This will be handled
|
374
|
-
as explaned above.
|
375
|
-
|
376
523
|
## Roadmap
|
377
524
|
|
378
|
-
* Methods to create new locations and mapsets.
|
379
525
|
* Change Module to define explicitly available GRASS commands instead of
|
380
526
|
accepting anything with `method_missing`. Declare commands with permitted
|
381
527
|
arguments and options, etc.
|
@@ -385,6 +531,8 @@ as explaned above.
|
|
385
531
|
- Methods to check if maps exist
|
386
532
|
- Methods that return information as objects (arrays, hashes), e.g.
|
387
533
|
values returned by r.what, the current region, etc.
|
534
|
+
- Methods that execute operations in a GRASS-version independent
|
535
|
+
manner (higher level, version independent interface to modules).
|
388
536
|
|
389
537
|
### GRASS cooking DSL
|
390
538
|
|
data/lib/grassgis/context.rb
CHANGED
@@ -7,6 +7,7 @@ module GrassGis
|
|
7
7
|
REQUIRED_CONFIG = [:gisbase, :location]
|
8
8
|
|
9
9
|
def initialize(config)
|
10
|
+
# TODO: raise error unless required parameters are present
|
10
11
|
# apply configuration defaults
|
11
12
|
config[:gisdbase] ||= File.join(ENV['HOME'], 'grassdata')
|
12
13
|
config[:mapset] ||= ENV['USER']
|
@@ -82,16 +83,12 @@ module GrassGis
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def allocate
|
85
|
-
@gisrc = Tempfile.new('gisrc')
|
86
|
-
@gisrc.puts "LOCATION_NAME: #{@config[:location]}"
|
87
|
-
@gisrc.puts "GISDBASE: #{@config[:gisdbase]}"
|
88
|
-
@gisrc.puts "MAPSET: #{@config[:mapset]}"
|
89
|
-
@gisrc.puts "GUI: #{@config[:gui]}"
|
90
|
-
@gisrc.close
|
91
|
-
|
92
86
|
@original_env = {}
|
93
87
|
|
94
|
-
|
88
|
+
mapset = Mapset.new(self)
|
89
|
+
actual_mapset = mapset.exists? ? mapset.to_s : 'PERMANENT'
|
90
|
+
set_gisrc @config.merge(mapset: actual_mapset)
|
91
|
+
|
95
92
|
replace_var 'GISBASE', @config[:gisbase]
|
96
93
|
replace_var 'GRASS_VERSION', @config[:version]
|
97
94
|
replace_var 'GRASS_MESSAGE_FORMAT', @config[:message_format].to_s
|
@@ -123,8 +120,10 @@ module GrassGis
|
|
123
120
|
def dispose
|
124
121
|
@gisrc.unlink if @gisrc
|
125
122
|
@gisrc = nil
|
126
|
-
@original_env
|
127
|
-
|
123
|
+
if @original_env
|
124
|
+
@original_env.each do |var, value|
|
125
|
+
ENV[var] = value
|
126
|
+
end
|
128
127
|
end
|
129
128
|
@original_env = {}
|
130
129
|
end
|
@@ -177,11 +176,7 @@ module GrassGis
|
|
177
176
|
if @config[:echo]
|
178
177
|
puts cmd.to_s(with_input: false)
|
179
178
|
end
|
180
|
-
|
181
|
-
if log_file
|
182
|
-
log_timestamp log_file
|
183
|
-
log log_file, cmd.to_s(with_input: true)
|
184
|
-
end
|
179
|
+
log("Execute command:") { cmd.to_s(with_input: true) }
|
185
180
|
unless dry?
|
186
181
|
cmd.run error_output: :separate
|
187
182
|
end
|
@@ -192,15 +187,82 @@ module GrassGis
|
|
192
187
|
cmd
|
193
188
|
end
|
194
189
|
|
190
|
+
def log(text, options = {})
|
191
|
+
log_file = logging_file
|
192
|
+
if log_file
|
193
|
+
timestamp = Time.now.strftime("%H:%M:%S")
|
194
|
+
msg = "#{timestamp} - #{text}"
|
195
|
+
log_message log_file, msg
|
196
|
+
indented_text = options[:indented]
|
197
|
+
indented_text ||= yield if !indented_text && block_given?
|
198
|
+
if indented_text
|
199
|
+
log_message log_file, indented_text, indentation: ' '
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def logging?
|
205
|
+
!!logging_file
|
206
|
+
end
|
207
|
+
|
208
|
+
# This should be used instead of g.mapset to avoid problems under Windows
|
209
|
+
def change_mapset(new_mapset)
|
210
|
+
log "Change mapset to #{new_mapset}"
|
211
|
+
set_gisrc @config.merge(mapset: new_mapset)
|
212
|
+
end
|
213
|
+
|
214
|
+
def log_header
|
215
|
+
log_file = logging_file
|
216
|
+
if log_file
|
217
|
+
msg = "Start GrassGis Session [#{Time.now}]"
|
218
|
+
log_message log_file, "# #{'='*msg.size}"
|
219
|
+
log_message log_file, "# #{msg}"
|
220
|
+
log_message log_file, configuration.to_yaml, indentation: '# '
|
221
|
+
log_message log_file, "# #{'-'*msg.size}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Version of GRASS in use in the session, as a comparable version
|
226
|
+
# object.
|
227
|
+
#
|
228
|
+
# Example of use:
|
229
|
+
#
|
230
|
+
# GrassGis.session configuration do
|
231
|
+
# if grass_version >= GrassGis.version('7.0.0')
|
232
|
+
# r.relief input: 'dem', output: 'relief'
|
233
|
+
# else
|
234
|
+
# r.shaded.relief map: 'dem', shadedmap: 'relief'
|
235
|
+
# end
|
236
|
+
# end
|
237
|
+
#
|
238
|
+
def grass_version
|
239
|
+
Gem::Version.new @config[:version]
|
240
|
+
end
|
241
|
+
|
195
242
|
private
|
196
243
|
|
197
|
-
def
|
198
|
-
|
244
|
+
def set_gisrc(options)
|
245
|
+
@old_gisrc = @gisrc
|
246
|
+
@gisrc = Tempfile.new('gisrc')
|
247
|
+
@gisrc.puts "GISDBASE: #{options[:gisdbase]}" if options[:gisdbase]
|
248
|
+
@gisrc.puts "LOCATION_NAME: #{options[:location]}" if options[:location]
|
249
|
+
@gisrc.puts "MAPSET: #{options[:mapset]}" if options[:mapset]
|
250
|
+
@gisrc.puts "GUI: #{options[:gui]}" if options[:gui]
|
251
|
+
@gisrc.close
|
252
|
+
replace_var 'GISRC', @gisrc.path
|
253
|
+
@old_gisrc.unlink if @old_gisrc
|
199
254
|
end
|
200
255
|
|
201
|
-
def
|
256
|
+
def logging_file
|
257
|
+
@config[:log] || @config[:history]
|
258
|
+
end
|
259
|
+
|
260
|
+
def log_message(file, message, options = {})
|
202
261
|
if file && message
|
203
262
|
File.open(file, 'a') do |log_file|
|
263
|
+
if options[:indentation]
|
264
|
+
message = message.gsub(/^/, options[:indentation])
|
265
|
+
end
|
204
266
|
log_file.puts message
|
205
267
|
end
|
206
268
|
end
|
@@ -214,7 +276,7 @@ module GrassGis
|
|
214
276
|
if @config[:errors] == :console || @config[:echo] == :output
|
215
277
|
STDERR.puts error_info
|
216
278
|
end
|
217
|
-
log
|
279
|
+
log "Error:", indented: error_info
|
218
280
|
end
|
219
281
|
end
|
220
282
|
end
|
@@ -233,7 +295,7 @@ module GrassGis
|
|
233
295
|
end
|
234
296
|
|
235
297
|
def replace_var(var, value)
|
236
|
-
@original_env[var]
|
298
|
+
@original_env[var] ||= ENV[var]
|
237
299
|
ENV[var] = value
|
238
300
|
end
|
239
301
|
|
@@ -312,14 +374,13 @@ module GrassGis
|
|
312
374
|
def self.session(config, &blk)
|
313
375
|
context = Context.new(config)
|
314
376
|
context.allocate
|
377
|
+
context.log_header
|
378
|
+
create context, config[:create]
|
315
379
|
context.session &blk
|
316
380
|
ensure
|
317
381
|
context.dispose if context
|
318
382
|
end
|
319
383
|
|
320
|
-
class Error < StandardError
|
321
|
-
end
|
322
|
-
|
323
384
|
def self.error?(command)
|
324
385
|
command && (!!command.error || (command.status_value && command.status_value != 0))
|
325
386
|
end
|
@@ -351,4 +412,32 @@ module GrassGis
|
|
351
412
|
end
|
352
413
|
end
|
353
414
|
|
415
|
+
# Return a comparable Version object from a version number string
|
416
|
+
def self.version(version)
|
417
|
+
Gem::Version.new version
|
418
|
+
end
|
419
|
+
|
420
|
+
class <<self
|
421
|
+
private
|
422
|
+
def create(context, options)
|
423
|
+
return unless options
|
424
|
+
gisdbase = context.configuration[:gisdbase]
|
425
|
+
unless File.directory?(gisdbase)
|
426
|
+
context.log "Create GISDBASE #{gisdbase}"
|
427
|
+
FileUtils.mkdir_p gisdbase
|
428
|
+
end
|
429
|
+
location = Location.new(context)
|
430
|
+
unless location.exists?
|
431
|
+
context.log "Create location #{location} at #{gisdbase}"
|
432
|
+
location.create! options
|
433
|
+
end
|
434
|
+
mapset = Mapset.new(context)
|
435
|
+
unless mapset.exists?
|
436
|
+
context.log "Create mapset #{mapset} at location #{location.path}"
|
437
|
+
mapset.create! options
|
438
|
+
end
|
439
|
+
# context.g.mapset mapset: mapset.to_s, location: location.to_s, dbase: gisdbase
|
440
|
+
context.change_mapset mapset.to_s
|
441
|
+
end
|
442
|
+
end
|
354
443
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module GrassGis
|
2
|
+
class Location
|
3
|
+
def initialize(context)
|
4
|
+
@context = context
|
5
|
+
@configuration = @context.configuration
|
6
|
+
@gisdbase = @configuration[:gisdbase]
|
7
|
+
@location = @configuration[:location]
|
8
|
+
@path = File.join(@gisdbase, @location)
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :path
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
@location
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
File.directory?(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create!(options = {})
|
22
|
+
raise Error, "Location #{@location} already exists" if exists?
|
23
|
+
raise Error, "A file with the same name #{@location} exists" if File.exists?(@path)
|
24
|
+
raise Error, "GRASSDBASE doesn't exist" unless File.directory?(@gisdbase)
|
25
|
+
epsg = options[:epsg]
|
26
|
+
limits = options[:limits]
|
27
|
+
desc = options[:desc]
|
28
|
+
raise Error, "An EPSG code is needed to define a new loaction" unless epsg
|
29
|
+
@context.g.proj '-t', epsg: epsg, location: @location
|
30
|
+
permanent = permanent_path
|
31
|
+
if desc
|
32
|
+
desc_file = File.join(permanent, 'MYNAME')
|
33
|
+
File.write desc_file, desc
|
34
|
+
end
|
35
|
+
if limits
|
36
|
+
w, s, e, n = limits
|
37
|
+
res = options[:res]
|
38
|
+
# @context.g.mapset mapset: 'PERMANENT', location: @location
|
39
|
+
@context.change_mapset 'PERMANENT'
|
40
|
+
@context.g.region w: w, s: s, e: e, n: n, res: res
|
41
|
+
FileUtils.cp File.join(permanent, 'WIND'), File.join(permanent, 'DEFAULT_WIND')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def mapset_path(mapset)
|
46
|
+
File.join(@path, mapset)
|
47
|
+
end
|
48
|
+
|
49
|
+
def permanent_path
|
50
|
+
mapset_path('PERMANENT')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module GrassGis
|
2
|
+
class Mapset
|
3
|
+
def initialize(context)
|
4
|
+
@context = context
|
5
|
+
@configuration = @context.configuration
|
6
|
+
@location = Location.new(@context)
|
7
|
+
@mapset = @configuration[:mapset]
|
8
|
+
@path = File.join(@location.path, @mapset)
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :path
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
@mapset
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
File.directory?(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create!(options = {})
|
22
|
+
raise Error, "Mapset #{@mapset} already exists" if exists?
|
23
|
+
raise Error, "A file with the same name #{@mapset} exists" if File.exists?(@path)
|
24
|
+
raise Error, "Location doesn't exist" unless @location.exists?
|
25
|
+
# @context.g.mapet '-c', mapset: @mapset, location: @location.to_s, dbase: @configuration[:gisdbase]
|
26
|
+
FileUtils.mkdir_p @path
|
27
|
+
permanent = @location.permanent_path
|
28
|
+
FileUtils.cp File.join(permanent, 'DEFAULT_WIND'), File.join(@path, 'WIND')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/grassgis/module.rb
CHANGED
data/lib/grassgis/version.rb
CHANGED
data/lib/grassgis.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grassgis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Goizueta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sys_cmd
|
@@ -82,6 +82,9 @@ files:
|
|
82
82
|
- grassgis.gemspec
|
83
83
|
- lib/grassgis.rb
|
84
84
|
- lib/grassgis/context.rb
|
85
|
+
- lib/grassgis/error.rb
|
86
|
+
- lib/grassgis/location.rb
|
87
|
+
- lib/grassgis/mapset.rb
|
85
88
|
- lib/grassgis/module.rb
|
86
89
|
- lib/grassgis/support.rb
|
87
90
|
- lib/grassgis/version.rb
|