예제 #1
0
    def __init__(self, name, mapset="", *aopen, **kwopen):
        """The constructor need at least the name of the map
        *optional* field is the `mapset`.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> ele.name
        u'abstract_test_map'
        >>> ele.exist()
        True

        ..
        """
        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
예제 #2
0
 def testCategory(self):
     r = RasterRow(self.name)
     r.open()
     cats = r.cats
     cats1 = Category(self.name)
     cats1.read()
     self.assertEqual(cats, cats1)
     r.close()
예제 #3
0
 def testCategory(self):
     r = RasterRow(self.name)
     r.open()
     cats = r.cats
     cats1 = Category(self.name)
     cats1.read()
     self.assertEqual(cats, cats1)
     r.close()
예제 #4
0
 def testFirstCat(self):
     cat0 = ('A', 11, None)
     cat7 = ('H', 24, None)
     cat15 = ('P', 44, None)
     cats = Category(self.name)
     cats.read()
     self.assertEqual(cats[0], cat0)
     self.assertEqual(cats[7], cat7)
     self.assertEqual(cats[15], cat15)
예제 #5
0
 def testCategory(self):
     r = RasterRow(self.name)
     r.open()
     cats = r.cats
     cats1 = Category(self.name)
     cats1.read()
     # this is not working, I don't know why
     self.assertEqual(cats, cats1)
     r.close()
예제 #6
0
 def testCategory(self):
     r = RasterRow(self.name)
     r.open()
     cats = r.cats
     cats1 = Category(self.name)
     cats1.read()
     # this is not working, I don't know why
     self.assertEqual(cats, cats1)
     r.close()
예제 #7
0
 def testFirstCat(self):
     cat0 = ('A', 11, None)
     cat7 = ('H', 24, None)
     cat15 = ('P', 44, None)
     cats = Category(self.name)
     cats.read()
     self.assertEqual(cats[0], cat0)
     self.assertEqual(cats[7], cat7)
     self.assertEqual(cats[15], cat15)
예제 #8
0
    def __init__(self, name, mapset="", *aopen, **kwopen):
        """The constructor need at least the name of the map
        *optional* field is the `mapset`.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> ele.name
        u'abstract_test_map'
        >>> ele.exist()
        True

        ..
        """
        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
예제 #9
0
파일: abstract.py 프로젝트: pesekon2/grass
    def __init__(self, name, mapset="", *aopen, **kwopen):
        """The constructor need at least the name of the map
        *optional* field is the `mapset`.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> ele.name
        'abstract_test_map'
        >>> ele.exist()
        True

        ..
        """
        self.mapset = mapset
        if not mapset:
            # note that @must_be_in_current_mapset requires mapset to be set
            mapset = libgis.G_find_raster(name, mapset)
            if mapset is not None:
                self.mapset = utils.decode(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
예제 #10
0
파일: abstract.py 프로젝트: pesekon2/grass
 def get_cats(self):
     """Return a category object"""
     cat = Category(name=self.name, mapset=self.mapset)
     cat.read()
     return cat
예제 #11
0
파일: abstract.py 프로젝트: pesekon2/grass
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(test_raster_name)
        >>> ele.name
        'abstract_test_map'
        >>> ele.exist()
        True

        ..
        """
        self.mapset = mapset
        if not mapset:
            # note that @must_be_in_current_mapset requires mapset to be set
            mapset = libgis.G_find_raster(name, mapset)
            if mapset is not None:
                self.mapset = utils.decode(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"):
            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):
            # 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 not self.is_open():
                raise IndexError(
                    "Can not operate on a closed map. Call open() first.")
            if key < 0:  # Handle negative indices
                key += self._rows
            if key >= self._rows:
                raise IndexError(
                    "The row index {0} is out of range [0, {1}).".format(
                        key, self._rows))
            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))

    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(test_raster_name)
        >>> 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

    def is_open(self):
        """Return True if the map is open False otherwise.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> ele.is_open()
        False

        """
        return True if self._fd is not None and self._fd >= 0 else False

    @must_be_open
    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

    def remove(self):
        """Remove the map"""
        if self.is_open():
            self.close()
        utils.remove(self.name, "rast")

    def fullname(self):
        """Return the full name of a raster map: name@mapset"""
        return "{name}@{mapset}".format(name=self.name, mapset=self.mapset)

    def name_mapset(self, name=None, mapset=None):
        """Return the full name of the Raster.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> name = ele.name_mapset().split("@")
        >>> name
        ['abstract_test_map']

        """
        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

    def rename(self, newname):
        """Rename the map"""
        if self.exist():
            utils.rename(self.name, newname, "rast")
        self._name = newname

    def set_region_from_rast(self, rastname="", mapset=""):
        """Set the computational region from a map,
        if rastername and mapset is not specify, use itself.
        This region will be used by all
        raster map layers that are opened in the same process.

        The GRASS region settings will not be modified.

        call C function `Rast_get_cellhd`, `Rast_set_window`

        """
        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, region.byref())
        self._set_raster_window(region)

    def set_region(self, region):
        """Set the computational region that can be different from the
        current region settings. This region will be used by all
        raster map layers that are opened in the same process.

        The GRASS region settings will not be modified.
        """
        if self.is_open():
            fatal("You cannot change the region if map is open")
            raise
        self._set_raster_window(region)

    def _set_raster_window(self, region):
        libraster.Rast_set_window(region.byref())
        # update rows and cols attributes
        self._rows = libraster.Rast_window_rows()
        self._cols = libraster.Rast_window_cols()

    @must_be_open
    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 or class object with coords() method
        """
        # Check for tuple
        if not isinstance(point, list) and not isinstance(point, tuple):
            point = point.coords()

        if not region:
            region = Region()
        row, col = utils.coor2pixel(point, 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
    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
    def num_cats(self):
        """Return the number of categories"""
        return len(self.cats)

    @must_be_open
    def copy_cats(self, raster):
        """Copy categories from another raster map object"""
        self.cats.copy(raster.cats)

    @must_be_open
    def sort_cats(self):
        """Sort categories order by range"""
        self.cats.sort()

    @must_be_open
    def read_cats(self):
        """Read category from the raster map file"""
        self.cats.read(self)

    @must_be_open
    def write_cats(self):
        """Write category to the raster map file"""
        self.cats.write(self)

    @must_be_open
    def read_cats_rules(self, filename, sep=":"):
        """Read category from the raster map file"""
        self.cats.read_rules(filename, sep)

    @must_be_open
    def write_cats_rules(self, filename, sep=":"):
        """Write category to the raster map file"""
        self.cats.write_rules(filename, sep)

    @must_be_open
    def get_cats(self):
        """Return a category object"""
        cat = Category(name=self.name, mapset=self.mapset)
        cat.read()
        return cat

    @must_be_open
    def set_cats(self, category):
        """The internal categories are copied from this object."""
        self.cats.copy(category)

    @must_be_open
    def get_cat(self, label):
        """Return a category given an index or a label"""
        return self.cats[label]

    @must_be_open
    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))
예제 #12
0
 def testWrite(self):
     tmpfile = tempfile(False)
     cats = Category(self.name)
     cats.read()
     cats.write_rules(tmpfile)
     self.assertFilesEqualMd5(tmpfile, 'data/geology_cats')
예제 #13
0
 def get_cats(self):
     """Return a category object"""
     cat = Category()
     cat.read(self)
     return cat
예제 #14
0
 def testFirstCat(self):
     cat0 = ("Zml", 1, None)
     cats = Category(self.name)
     cats.read()
     self.assertEqual(cats[0], cat0)
예제 #15
0
 def testFirstCat(self):
     cat0 = ('Zml', 1, None)
     cats = Category(self.name)
     cats.read()
     self.assertEqual(cats[0], cat0)
예제 #16
0
 def get_cats(self):
     """Return a category object"""
     cat = Category()
     cat.read(self)
     return cat
예제 #17
0
 def testWrite(self):
     tmpfile = tempfile(False)
     cats = Category(self.name)
     cats.read()
     cats.write_rules(tmpfile)
     self.assertFilesEqualMd5(tmpfile, 'data/geology_cats')
예제 #18
0
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(test_raster_name)
        >>> ele.name
        u'abstract_test_map'
        >>> ele.exist()
        True

        ..
        """
        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))

    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(test_raster_name)
        >>> 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

    def is_open(self):
        """Return True if the map is open False otherwise.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> ele.is_open()
        False

        """
        return True if self._fd is not None and self._fd >= 0 else False

    @must_be_open
    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

    def remove(self):
        """Remove the map"""
        if self.is_open():
            self.close()
        utils.remove(self.name, 'rast')

    def fullname(self):
        """Return the full name of a raster map: name@mapset"""
        return "{name}@{mapset}".format(name=self.name, mapset=self.mapset)

    def name_mapset(self, name=None, mapset=None):
        """Return the full name of the Raster.

        >>> ele = RasterAbstractBase(test_raster_name)
        >>> name = ele.name_mapset().split("@")
        >>> name
        [u'abstract_test_map']

        """
        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

    def rename(self, newname):
        """Rename the map"""
        if self.exist():
            utils.rename(self.name, newname, 'rast')
        self._name = newname

    def set_region_from_rast(self, rastname='', mapset=''):
        """Set the computational region from a map,
           if rastername and mapset is not specify, use itself.
           This region will be used by all
           raster map layers that are opened in the same process.

           The GRASS region settings will not be modified.

           call C function `Rast_get_cellhd`, `Rast_set_window`

           """
        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,
                                  region.byref())
        self._set_raster_window(region)

    def set_region(self, region):
        """Set the computational region that can be different from the
           current region settings. This region will be used by all
           raster map layers that are opened in the same process.

           The GRASS region settings will not be modified.
        """
        if self.is_open():
            fatal("You cannot change the region if map is open")
            raise
        self._set_raster_window(region)

    def _set_raster_window(self, region):
        libraster.Rast_set_window(region.byref())
        # update rows and cols attributes
        self._rows = libraster.Rast_window_rows()
        self._cols = libraster.Rast_window_cols()

    @must_be_open
    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 or class object with coords() method
        """
        # Check for tuple
        if type(point) != type([]) and type(point) != type(()):
            point = point.coords()

        if not region:
            region = Region()
        row, col = utils.coor2pixel(point, 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
    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
    def num_cats(self):
        """Return the number of categories"""
        return len(self.cats)

    @must_be_open
    def copy_cats(self, raster):
        """Copy categories from another raster map object"""
        self.cats.copy(raster.cats)

    @must_be_open
    def sort_cats(self):
        """Sort categories order by range"""
        self.cats.sort()

    @must_be_open
    def read_cats(self):
        """Read category from the raster map file"""
        self.cats.read(self)

    @must_be_open
    def write_cats(self):
        """Write category to the raster map file"""
        self.cats.write(self)

    @must_be_open
    def read_cats_rules(self, filename, sep=':'):
        """Read category from the raster map file"""
        self.cats.read_rules(filename, sep)

    @must_be_open
    def write_cats_rules(self, filename, sep=':'):
        """Write category to the raster map file"""
        self.cats.write_rules(filename, sep)

    @must_be_open
    def get_cats(self):
        """Return a category object"""
        cat = Category()
        cat.read(self)
        return cat

    @must_be_open
    def set_cats(self, category):
        """The internal categories are copied from this object."""
        self.cats.copy(category)

    @must_be_open
    def get_cat(self, label):
        """Return a category given an index or a label"""
        return self.cats[label]

    @must_be_open
    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))