class GrassGis::Context

Constants

REQUIRED_CONFIG
ROOT_MODULES

Attributes

history[R]

Commands executed in the session are kept in the history array

GrassGis.session config do
   g.region res: 10
   g.region res: 20
   g.region res: 30
   puts history[-3] # => "g.region res=10"
   puts history[-2] # => "g.region res=20"
   puts history[-1] # => "g.region res=30"
   puts history[-2].output
end

Public Class Methods

new(config) click to toggle source
# File lib/grassgis/context.rb, line 9
def initialize(config)
  # TODO: raise error unless required parameters are present
  # apply configuration defaults
  config[:gisdbase] ||= File.join(ENV['HOME'], 'grassdata')
  config[:mapset]  ||= ENV['USER']
  unless config[:version]
    version_file = File.join(config[:gisbase], 'etc', 'VERSIONNUMBER')
    if File.exists?(version_file)
      config[:version] = File.read(version_file).split.first
    end
  end
  config[:message_format] ||= 'plain'
  config[:true_color] = true unless config.key?(:true_color)
  config[:transparent] = true unless config.key?(:transparent)
  config[:png_auto_write] = true unless config.key?(:png_auto_write)
  config[:gnuplot] ||= 'gnuplot -persist'
  config[:gui] ||= 'wxpython'
  config[:python] ||= 'python'
  config[:pythonpath] ||= File.join(config[:gisbase], 'etc', 'python')

  config[:errors] ||= :raise
  config[:echo] = :commands unless config.key?(:echo)

  @config = config
  @tools = (config[:tools] == false) ? false : true

  locals = config[:locals] || {}
  locals.each do |var_name, value|
    define_singleton_method(var_name){ value }
  end
end

Public Instance Methods

allocate() click to toggle source
# File lib/grassgis/context.rb, line 88
def allocate
  @original_env = {}

  mapset = Mapset.new(self)
  actual_mapset = mapset.exists? ? mapset.to_s : 'PERMANENT'
  set_gisrc @config.merge(mapset: actual_mapset)

  replace_var 'GISBASE', @config[:gisbase]
  replace_var 'GRASS_VERSION', @config[:version]
  replace_var 'GRASS_MESSAGE_FORMAT', @config[:message_format].to_s
  replace_var 'GRASS_TRUECOLOR', bool_var(@config[:true_color])
  replace_var 'GRASS_TRANSPARENT', bool_var(@config[:transparent])
  replace_var 'GRASS_PNG_AUTO_WRITE', bool_var(@config[:png_auto_write])
  replace_var 'GRASS_GNUPLOT', @config[:gnuplot]
  replace_var 'GRASS_PYTHON', @config[:python]
  insert_path 'PYTHONPATH', @config[:pythonpath]

  paths = ['bin', 'scripts']
  if OS.windows?
    # paths << 'lib'
    paths.unshift 'lib'
  else
    insert_path 'LD_LIBRARY_PATH', File.join(@config[:gisbase], 'lib')
    ENV['GRASS_LD_LIBRARY_PATH'] = ENV['LD_LIBRARY_PATH']
  end
  paths = paths.map { |path| File.join(@config[:gisbase], path) }
  if OS.windows?
    osgeo4w_dir = ENV['OSGEO4W_ROOT'] || "C:\\OSGeo4W"
    if File.directory?(osgeo4w_dir)
      paths << File.join(osgeo4w_dir, 'bin')
    end
  end
  insert_path 'PATH', *paths
  insert_path 'MANPATH', File.join(@config[:gisbase], 'man')
  @history = []
  extend GrassGis::Tools if @tools
end
change_mapset(new_mapset) click to toggle source

This should be used instead of g.mapset to avoid problems under Windows

# File lib/grassgis/context.rb, line 215
def change_mapset(new_mapset)
  log "Change mapset to #{new_mapset}"
  set_gisrc @config.merge(mapset: new_mapset)
end
configuration() click to toggle source
# File lib/grassgis/context.rb, line 84
def configuration
  @config
end
dispose() click to toggle source
# File lib/grassgis/context.rb, line 126
def dispose
  @gisrc.unlink if @gisrc
  @gisrc = nil
  if @original_env
    @original_env.each do |var, value|
      ENV[var] = value
    end
  end
  @original_env = {}
end
dry?() click to toggle source
# File lib/grassgis/context.rb, line 176
def dry?
  @config[:dry]
end
error?() click to toggle source

Did last command exit with error status

# File lib/grassgis/context.rb, line 66
def error?
  GrassGis.error? last
end
error_info() click to toggle source
# File lib/grassgis/context.rb, line 70
def error_info
  GrassGis.error_info last
end
error_output() click to toggle source

Standar error output of last command executed

# File lib/grassgis/context.rb, line 80
def error_output
  last.error_output
end
errors() click to toggle source

Array of commands that resulted in error in the session

# File lib/grassgis/context.rb, line 61
def errors
  history.select { |cmd| GrassGis.error?(cmd) }
end
execute(cmd) click to toggle source
# File lib/grassgis/context.rb, line 180
def execute(cmd)
  @history << cmd
  if @config[:echo]
    puts cmd.to_s(with_input: false)
  end
  log("Execute command:") { cmd.to_s(with_input: true) }
  unless dry?
    cmd.run error_output: :separate
  end
  if cmd.output
    puts cmd.output if @config[:echo] == :output
  end
  handle_errors cmd
  cmd
end
grass_version() click to toggle source

Version of GRASS in use in the session, as a comparable version object.

Example of use:

GrassGis.session configuration do
  if grass_version >= GrassGis.version('7.0.0')
    r.relief input: 'dem', output: 'relief'
  else
    r.shaded.relief map: 'dem', shadedmap: 'relief'
  end
end
# File lib/grassgis/context.rb, line 244
def grass_version
  GrassGis.version @config[:version]
end
last() click to toggle source

Last command executed in the session (history)

# File lib/grassgis/context.rb, line 56
def last
  history.last
end
log(text, options = {}) { || ... } click to toggle source
# File lib/grassgis/context.rb, line 196
def log(text, options = {})
  log_file = logging_file
  if log_file
    timestamp = Time.now.strftime("%H:%M:%S")
    msg = "#{timestamp} - #{text}"
    log_message log_file, msg
    indented_text = options[:indented]
    indented_text ||= yield if !indented_text && block_given?
    if indented_text
      log_message log_file, indented_text, indentation: '  '
    end
  end
end
log_header() click to toggle source
# File lib/grassgis/context.rb, line 220
def log_header
  log_file = logging_file
  if log_file
    msg = "Start GrassGis Session [#{Time.now}]"
    log_message log_file, "# #{'='*msg.size}"
    log_message log_file, "# #{msg}"
    log_message log_file, configuration.to_yaml, indentation: '# '
    log_message log_file, "# #{'-'*msg.size}"
  end
end
logging?() click to toggle source
# File lib/grassgis/context.rb, line 210
def logging?
  !!logging_file
end
output() click to toggle source

Output of the last command executed

# File lib/grassgis/context.rb, line 75
def output
  last.output
end
session(&blk) click to toggle source

Evaluate a block of code in the context of a GRASS session

Useful to pass a GRASS context around and use it to execute GRASS commands, e.g.:

def helper(grass, ...)
   # can invoke GRASS commands using grass:
   grass.g.region res: 10
   # Or use a session block to abbreviate typing:
   grass.session do
     g.region res: 10
     ...
   end
end

GrassGis.session ... do
  helper seld, ...
  ...
end
# File lib/grassgis/context.rb, line 168
def session(&blk)
  if blk.arity == 1
    blk.call self
  else
    instance_eval &blk
  end
end

Private Instance Methods

bool_var(value) click to toggle source
# File lib/grassgis/context.rb, line 290
def bool_var(value)
  value ? 'TRUE' : 'FALSE'
end
handle_errors(cmd) click to toggle source
# File lib/grassgis/context.rb, line 277
def handle_errors(cmd)
  GrassGis.error cmd, @config[:errors]
  if @config[:echo] == :output || @config[:log] || @config[:errors] == :console
    error_info = GrassGis.error_info(cmd)
    if error_info
      if @config[:errors] == :console || @config[:echo] == :output
        STDERR.puts error_info
      end
      log "Error:", indented: error_info
    end
  end
end
insert_path(var, *paths) click to toggle source
# File lib/grassgis/context.rb, line 294
def insert_path(var, *paths)
  @original_env[var] = ENV[var]
  if File::ALT_SEPARATOR
    paths = paths.map { |path| path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) }
  end
  paths << ENV[var] if ENV[var]
  ENV[var] = paths.join(File::PATH_SEPARATOR)
end
log_message(file, message, options = {}) click to toggle source
# File lib/grassgis/context.rb, line 266
def log_message(file, message, options = {})
  if file && message
    File.open(file, 'a') do |log_file|
      if options[:indentation]
        message = message.gsub(/^/, options[:indentation])
      end
      log_file.puts message
    end
  end
end
logging_file() click to toggle source
# File lib/grassgis/context.rb, line 262
def logging_file
  @config[:log] || @config[:history]
end
replace_var(var, value) click to toggle source
# File lib/grassgis/context.rb, line 303
def replace_var(var, value)
  @original_env[var] ||= ENV[var]
  ENV[var] = value
end
set_gisrc(options) click to toggle source
# File lib/grassgis/context.rb, line 250
def set_gisrc(options)
  @old_gisrc = @gisrc
  @gisrc = Tempfile.new('gisrc')
  @gisrc.puts "GISDBASE: #{options[:gisdbase]}"      if options[:gisdbase]
  @gisrc.puts "LOCATION_NAME: #{options[:location]}" if options[:location]
  @gisrc.puts "MAPSET: #{options[:mapset]}"          if options[:mapset]
  @gisrc.puts "GUI: #{options[:gui]}"                if options[:gui]
  @gisrc.close
  replace_var 'GISRC', @gisrc.path
  @old_gisrc.unlink if @old_gisrc
end