# -*- coding: utf-8 -*-
"""
Created on Fri Aug 17 16:05:25 2012
@author: pietro
"""
from __future__ import (nested_scopes, generators, division, absolute_import,
with_statement, print_function, unicode_literals)
import ctypes
#
# import GRASS modules
#
from grass.script import fatal, gisenv
import grass.lib.gis as libgis
import grass.lib.raster as libraster
#
# import pygrass modules
#
from grass.pygrass import utils
from grass.pygrass.gis.region import Region
from grass.pygrass.errors import must_be_open
from grass.pygrass.shell.conversion import dict2html
from grass.pygrass.shell.show import raw_figure
#
# import raster classes
#
from grass.pygrass.raster.raster_type import TYPE as RTYPE, RTYPE_STR
from grass.pygrass.raster.category import Category
from grass.pygrass.raster.history import History
## Define global variables to not exceed the 80 columns
WARN_OVERWRITE = "Raster map <{0}> already exists and will be overwritten"
INDXOUTRANGE = "The index (%d) is out of range, have you open the map?."
INFO = """{name}@{mapset}
rows: {rows}
cols: {cols}
north: {north} south: {south} nsres:{nsres}
east: {east} west: {west} ewres:{ewres}
range: {min}, {max}
proj: {proj}
"""
[docs]class Info(object):
def __init__(self, name, mapset=''):
"""Read the information for a raster map. ::
>>> info = Info('elevation')
>>> info.read()
>>> info
elevation@
rows: 1350
cols: 1500
north: 228500.0 south: 215000.0 nsres:10.0
east: 645000.0 west: 630000.0 ewres:10.0
range: 56, 156
proj: 99
<BLANKLINE>
"""
self.name = name
self.mapset = mapset
self.c_region = ctypes.pointer(libgis.Cell_head())
self.c_range = None
def _get_range(self):
if self.mtype == 'CELL':
self.c_range = ctypes.pointer(libraster.Range())
libraster.Rast_read_range(self.name, self.mapset, self.c_range)
else:
self.c_range = ctypes.pointer(libraster.FPRange())
libraster.Rast_read_fp_range(self.name, self.mapset, self.c_range)
def _get_raster_region(self):
libraster.Rast_get_cellhd(self.name, self.mapset, self.c_region)
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
[docs] def range(self):
if self.c_range is None:
return None, None
return self.c_range.contents.min, self.c_range.contents.max
@property
def _get_units(self):
return libraster.Rast_read_units(self.name, self.mapset)
def _set_units(self, units):
libraster.Rast_write_units(self.name, units)
units = property(_get_units, _set_units)
def _get_vdatum(self):
return libraster.Rast_read_vdatum(self.name, self.mapset)
def _set_vdatum(self, vdatum):
libraster.Rast_write_vdatum(self.name, vdatum)
vdatum = property(_get_vdatum, _set_vdatum)
def __repr__(self):
return INFO.format(name=self.name, mapset=self.mapset,
rows=self.rows, cols=self.cols,
north=self.north, south=self.south,
east=self.east, west=self.west,
top=self.top, bottom=self.bottom,
nsres=self.nsres, ewres=self.ewres,
tbres=self.tbres, zone=self.zone,
proj=self.proj, min=self.min, max=self.max)
[docs] def keys(self):
return ['name', 'mapset', 'rows', 'cols', 'north', 'south',
'east', 'west', 'top', 'bottom', 'nsres', 'ewres', 'tbres',
'zone', 'proj', 'min', 'max']
def _repr_html_(self):
return dict2html(dict(self.items()), keys=self.keys(),
border='1', kdec='b')
[docs]class RasterAbstractBase(object):
"""Raster_abstract_base: The base class from which all sub-classes
inherit. It does not implement any row or map access methods:
* Implements raster metadata information access (Type, ...)
* Implements an open method that will be overwritten by the sub-classes
* Implements the close method that might be overwritten by sub-classes
(should work for simple row access)
* Implements get and set region methods
* Implements color, history and category handling
* Renaming, deletion, ...
"""
def __init__(self, name, mapset="", *aopen, **kwopen):
"""The constructor need at least the name of the map
*optional* field is the `mapset`.
>>> ele = RasterAbstractBase('elevation')
>>> ele.name
u'elevation'
>>> ele.exist()
True
>>> ele.mapset
'PERMANENT'
..
"""
self.mapset = mapset
self._name = name
## Private attribute `_fd` that return the file descriptor of the map
self._fd = None
## Private attribute `_rows` that return the number of rows
# in active window, When the class is instanced is empty and it is set
# when you open the file, using Rast_window_rows()
self._rows = None
## Private attribute `_cols` that return the number of rows
# in active window, When the class is instanced is empty and it is set
# when you open the file, using Rast_window_cols()
self._cols = None
#self.region = Region()
self.hist = History(self.name, self.mapset)
self.cats = Category(self.name, self.mapset)
self.info = Info(self.name, self.mapset)
self._aopen = aopen
self._kwopen = kwopen
self._mtype = 'CELL'
self._mode = 'r'
self._overwrite = False
def __enter__(self):
self.open(*self._aopen, **self._kwopen)
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def _get_mtype(self):
"""Private method to get the Raster type"""
return self._mtype
def _set_mtype(self, mtype):
"""Private method to change the Raster type"""
if mtype.upper() not in ('CELL', 'FCELL', 'DCELL'):
#fatal(_("Raser type: {0} not supported".format(mtype) ) )
str_err = "Raster type: {0} not supported ('CELL','FCELL','DCELL')"
raise ValueError(_(str_err).format(mtype))
self._mtype = mtype
self._gtype = RTYPE[self.mtype]['grass type']
mtype = property(fget=_get_mtype, fset=_set_mtype)
def _get_mode(self):
return self._mode
def _set_mode(self, mode):
if mode.upper() not in ('R', 'W'):
str_err = _("Mode type: {0} not supported ('r', 'w')")
raise ValueError(str_err.format(mode))
self._mode = mode
mode = property(fget=_get_mode, fset=_set_mode)
def _get_overwrite(self):
return self._overwrite
def _set_overwrite(self, overwrite):
if overwrite not in (True, False):
str_err = _("Overwrite type: {0} not supported (True/False)")
raise ValueError(str_err.format(overwrite))
self._overwrite = overwrite
overwrite = property(fget=_get_overwrite, fset=_set_overwrite)
def _get_name(self):
"""Private method to return the Raster name"""
return self._name
def _set_name(self, newname):
"""Private method to change the Raster name"""
if not utils.is_clean_name(newname):
str_err = _("Map name {0} not valid")
raise ValueError(str_err.format(newname))
if self.exist():
self.rename(newname)
self._name = newname
name = property(fget=_get_name, fset=_set_name)
@must_be_open
def _get_cats_title(self):
return self.cats.title
@must_be_open
def _set_cats_title(self, newtitle):
self.cats.title = newtitle
cats_title = property(fget=_get_cats_title, fset=_set_cats_title)
def __unicode__(self):
return self.name_mapset()
def __str__(self):
"""Return the string of the object"""
return self.__unicode__()
def __len__(self):
return self._rows
def __getitem__(self, key):
"""Return the row of Raster object, slice allowed."""
if isinstance(key, slice):
#import pdb; pdb.set_trace()
#Get the start, stop, and step from the slice
return (self.get_row(ii) for ii in range(*key.indices(len(self))))
elif isinstance(key, tuple):
x, y = key
return self.get(x, y)
elif isinstance(key, int):
if key < 0: # Handle negative indices
key += self._rows
if key >= self._rows:
fatal(INDXOUTRANGE.format(key))
raise IndexError
return self.get_row(key)
else:
fatal("Invalid argument type.")
def __iter__(self):
"""Return a constructor of the class"""
return (self.__getitem__(irow) for irow in range(self._rows))
def _repr_png_(self):
return raw_figure(utils.r_export(self))
[docs] def exist(self):
"""Return True if the map already exist, and
set the mapset if were not set.
call the C function `G_find_raster`.
>>> ele = RasterAbstractBase('elevation')
>>> ele.exist()
True
"""
if self.name:
if self.mapset == '':
mapset = utils.get_mapset_raster(self.name, self.mapset)
self.mapset = mapset if mapset else ''
return True if mapset else False
return bool(utils.get_mapset_raster(self.name, self.mapset))
else:
return False
[docs] def is_open(self):
"""Return True if the map is open False otherwise.
>>> ele = RasterAbstractBase('elevation')
>>> ele.is_open()
False
"""
return True if self._fd is not None and self._fd >= 0 else False
@must_be_open
[docs] def close(self):
"""Close the map"""
libraster.Rast_close(self._fd)
# update rows and cols attributes
self._rows = None
self._cols = None
self._fd = None
[docs] def remove(self):
"""Remove the map"""
if self.is_open():
self.close()
utils.remove(self.name, 'rast')
[docs] def fullname(self):
"""Return the full name of a raster map: name@mapset"""
return "{name}@{mapset}".format(name=self.name, mapset=self.mapset)
[docs] def name_mapset(self, name=None, mapset=None):
"""Return the full name of the Raster.
>>> ele = RasterAbstractBase('elevation')
>>> ele.name_mapset()
u'elevation@PERMANENT'
"""
if name is None:
name = self.name
if mapset is None:
self.exist()
mapset = self.mapset
gis_env = gisenv()
if mapset and mapset != gis_env['MAPSET']:
return "{name}@{mapset}".format(name=name, mapset=mapset)
else:
return name
[docs] def rename(self, newname):
"""Rename the map"""
if self.exist():
utils.rename(self.name, newname, 'rast')
self._name = newname
[docs] def set_from_rast(self, rastname='', mapset=''):
"""Set the region that will use from a map, if rastername and mapset
is not specify, use itself.
call C function `Rast_get_cellhd`"""
if self.is_open():
fatal("You cannot change the region if map is open")
raise
region = Region()
if rastname == '':
rastname = self.name
if mapset == '':
mapset = self.mapset
libraster.Rast_get_cellhd(rastname, mapset,
ctypes.byref(region._region))
# update rows and cols attributes
self._rows = libraster.Rast_window_rows()
self._cols = libraster.Rast_window_cols()
@must_be_open
[docs] def get_value(self, point, region=None):
"""This method returns the pixel value of a given pair of coordinates:
:param point: pair of coordinates in tuple object
"""
if not region:
region = Region()
row, col = utils.coor2pixel(point.coords(), region)
if col < 0 or col > region.cols or row < 0 or row > region.rows:
return None
line = self.get_row(int(row))
return line[int(col)]
@must_be_open
[docs] def has_cats(self):
"""Return True if the raster map has categories"""
if self.exist():
self.cats.read()
if len(self.cats) != 0:
return True
return False
@must_be_open
@must_be_open
[docs] def copy_cats(self, raster):
"""Copy categories from another raster map object"""
self.cats.copy(raster.cats)
@must_be_open
@must_be_open
@must_be_open
@must_be_open
[docs] def read_cats_rules(self, filename, sep=':'):
"""Read category from the raster map file"""
self.cats.read_rules(filename, sep)
@must_be_open
[docs] def write_cats_rules(self, filename, sep=':'):
"""Write category to the raster map file"""
self.cats.write_rules(filename, sep)
@must_be_open
[docs] def get_cats(self):
"""Return a category object"""
cat = Category()
cat.read(self)
return cat
@must_be_open
[docs] def set_cats(self, category):
"""The internal categories are copied from this object."""
self.cats.copy(category)
@must_be_open
[docs] def get_cat(self, label):
"""Return a category given an index or a label"""
return self.cats[label]
@must_be_open
[docs] def set_cat(self, label, min_cat, max_cat=None, index=None):
"""Set or update a category"""
self.cats.set_cat(index, (label, min_cat, max_cat))
Help Index | Topics Index | Keywords Index | Full Index
© 2003-2018 GRASS Development Team, GRASS GIS 7.0.7svn Reference Manual