grassgis 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|