def __init__(self, name, srows=64, scols=64, maxmem=100, *args, **kargs): self.segment = Segment(srows, scols, maxmem) super(RasterSegment, self).__init__(name, *args, **kargs)
class RasterSegment(RasterAbstractBase): """Raster_segment_access": Inherits "Raster_abstract_base" and uses the segment library for cached randomly reading and writing access. * Implements the [row][col] operator for read and write access using Segment_get() and Segment_put() functions internally * Implements row read and write access with the [row] operator using Segment_get_row() Segment_put_row() internally * Implements the get_row() and put_row() method using Segment_get_row() Segment_put_row() internally * Implements the flush_segment() method * Implements the copying of raster maps to segments and vice verse * Overwrites the open and close methods * No mathematical operation like __add__ and stuff for the Raster object (only for rows), since r.mapcalc is more sophisticated and faster """ def __init__(self, name, srows=64, scols=64, maxmem=100, *args, **kargs): self.segment = Segment(srows, scols, maxmem) super(RasterSegment, self).__init__(name, *args, **kargs) def _get_mode(self): return self._mode def _set_mode(self, mode): if mode and mode.lower() not in ('r', 'w', 'rw'): str_err = _("Mode type: {0} not supported ('r', 'w','rw')") raise ValueError(str_err.format(mode)) self._mode = mode mode = property(fget=_get_mode, fset=_set_mode, doc="Set or obtain the opening mode of raster") def __setitem__(self, key, row): """Return the row of Raster object, slice allowed.""" if isinstance(key, slice): #Get the start, stop, and step from the slice return [self.put_row(ii, row) for ii in range(*key.indices(len(self)))] elif isinstance(key, tuple): x, y = key return self.put(x, y, row) elif isinstance(key, int): if key < 0: # Handle negative indices key += self._rows if key >= self._rows: raise IndexError(_("Index out of range: %r.") % key) return self.put_row(key, row) else: raise TypeError("Invalid argument type.") @must_be_open def map2segment(self): """Transform an existing map to segment file. """ row_buffer = Buffer((self._cols), self.mtype) for row in range(self._rows): libraster.Rast_get_row( self._fd, row_buffer.p, row, self._gtype) self.segment.put_row(row, row_buffer) @must_be_open def segment2map(self): """Transform the segment file to a map. """ row_buffer = Buffer((self._cols), self.mtype) for row in range(self._rows): row_buffer = self.segment.get_row(row, row_buffer) libraster.Rast_put_row(self._fd, row_buffer.p, self._gtype) @must_be_open def get_row(self, row, row_buffer=None): """Return the row using the `segment.get_row` method :param row: specify the row number :type row: int :param row_buffer: specify the Buffer object that will be instantiate :type row_buffer: Buffer object >>> elev = RasterRowIO(test_raster_name) >>> elev.open('r') >>> for row in elev: ... row Buffer([11, 21, 31, 41], dtype=int32) Buffer([12, 22, 32, 42], dtype=int32) Buffer([13, 23, 33, 43], dtype=int32) Buffer([14, 24, 34, 44], dtype=int32) >>> elev.close() >>> with RasterSegment(test_raster_name) as elev: ... for row in elev: ... row Buffer([11, 21, 31, 41], dtype=int32) Buffer([12, 22, 32, 42], dtype=int32) Buffer([13, 23, 33, 43], dtype=int32) Buffer([14, 24, 34, 44], dtype=int32) """ if row_buffer is None: row_buffer = Buffer((self._cols), self.mtype) return self.segment.get_row(row, row_buffer) @must_be_open def put_row(self, row, row_buffer): """Write the row using the `segment.put_row` method :param row: a Row object to insert into raster :type row: Buffer object Input and output must have the same type in case of row copy >>> map_a = RasterSegment(test_raster_name) >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_a.open('r') >>> map_b.open('w', mtype="CELL", overwrite=True) >>> for row in xrange(map_a.info.rows): ... map_b[row] = map_a[row] + 1000 >>> map_a.close() >>> map_b.close() >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_b.open("r") >>> for row in map_b: ... row Buffer([1011, 1021, 1031, 1041], dtype=int32) Buffer([1012, 1022, 1032, 1042], dtype=int32) Buffer([1013, 1023, 1033, 1043], dtype=int32) Buffer([1014, 1024, 1034, 1044], dtype=int32) >>> map_b.close() """ self.segment.put_row(row, row_buffer) @must_be_open def get(self, row, col): """Return the map value using the `segment.get` method :param row: Specify the row number :type row: int :param col: Specify the column number :type col: int >>> elev = RasterSegment(test_raster_name) >>> elev.open('r') >>> for i in xrange(4): ... elev.get(i,i) 11 22 33 44 >>> elev.close() >>> with RasterSegment(test_raster_name) as elev: ... elev.get(0,0) ... elev.get(1,1) ... elev.get(2,2) ... elev.get(3,3) 11 22 33 44 """ return self.segment.get(row, col) @must_be_open def put(self, row, col, val): """Write the value to the map using the `segment.put` method :param row: Specify the row number :type row: int :param col: Specify the column number :type col: int :param val: Specify the value that will be write to the map cell :type val: value >>> map_a = RasterSegment(test_raster_name) >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_a.open('r') >>> map_b.open('w', mtype="FCELL", overwrite=True) >>> for row in xrange(map_a.info.rows): ... for col in xrange(map_a.info.cols): ... value = map_a.get(row,col) ... map_b.put(row,col,value + 100) >>> map_a.close() >>> map_b.close() >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_b.open("r") >>> for row in map_b: ... row Buffer([ 111., 121., 131., 141.], dtype=float32) Buffer([ 112., 122., 132., 142.], dtype=float32) Buffer([ 113., 123., 133., 143.], dtype=float32) Buffer([ 114., 124., 134., 144.], dtype=float32) >>> map_b.close() """ self.segment.val.value = val self.segment.put(row, col) def open(self, mode=None, mtype=None, overwrite=None): """Open the map, if the map already exist: determine the map type and copy the map to the segment files; else, open a new segment map. :param mode: specify if the map will be open with read, write or read/write mode ('r', 'w', 'rw') :type mode: str :param mtype: specify the map type, valid only for new maps: CELL, FCELL, DCELL :type mtype: str :param overwrite: use this flag to set the overwrite mode of existing raster maps :type overwrite: bool """ # read rows and cols from the active region self._rows = libraster.Rast_window_rows() self._cols = libraster.Rast_window_cols() self.mode = mode if mode else self.mode self.mtype = mtype if mtype else self.mtype self.overwrite = overwrite if overwrite is not None else self.overwrite if self.exist(): self.info.read() self.cats.mtype = self.mtype self.cats.read() self.hist.read() if ((self.mode == "w" or self.mode == "rw") and self.overwrite is False): str_err = _("Raster map <{0}> already exists. Use overwrite.") fatal(str_err.format(self)) # We copy the raster map content into the segments if self.mode == "rw" or self.mode == "r": self._fd = libraster.Rast_open_old(self.name, self.mapset) self._gtype = libraster.Rast_get_map_type(self._fd) self.mtype = RTYPE_STR[self._gtype] # initialize the segment, I need to determine the mtype of the # map # before to open the segment self.segment.open(self) self.map2segment() self.segment.flush() self.cats.read() self.hist.read() if self.mode == "rw": #warning(_(WARN_OVERWRITE.format(self))) # Close the file descriptor and open it as new again libraster.Rast_close(self._fd) self._fd = libraster.Rast_open_new( self.name, self._gtype) # Here we simply overwrite the existing map without content copying elif self.mode == "w": #warning(_(WARN_OVERWRITE.format(self))) self._gtype = RTYPE[self.mtype]['grass type'] self.segment.open(self) self._fd = libraster.Rast_open_new(self.name, self._gtype) else: if self.mode == "r": str_err = _("Raster map <{0}> does not exist") raise OpenError(str_err.format(self.name)) self._gtype = RTYPE[self.mtype]['grass type'] self.segment.open(self) self._fd = libraster.Rast_open_new(self.name, self._gtype) @must_be_open def close(self, rm_temp_files=True): """Close the map, copy the segment files to the map. :param rm_temp_files: if True all the segments file will be removed :type rm_temp_files: bool """ if self.mode == "w" or self.mode == "rw": self.segment.flush() self.segment2map() if rm_temp_files: self.segment.close() else: self.segment.release() libraster.Rast_close(self._fd) # update rows and cols attributes self._rows = None self._cols = None self._fd = None
class RasterSegment(RasterAbstractBase): """Raster_segment_access": Inherits "Raster_abstract_base" and uses the segment library for cached randomly reading and writing access. * Implements the [row][col] operator for read and write access using Segment_get() and Segment_put() functions internally * Implements row read and write access with the [row] operator using Segment_get_row() Segment_put_row() internally * Implements the get_row() and put_row() method using Segment_get_row() Segment_put_row() internally * Implements the flush_segment() method * Implements the copying of raster maps to segments and vice verse * Overwrites the open and close methods * No mathematical operation like __add__ and stuff for the Raster object (only for rows), since r.mapcalc is more sophisticated and faster """ def __init__(self, name, srows=64, scols=64, maxmem=100, *args, **kargs): self.segment = Segment(srows, scols, maxmem) super(RasterSegment, self).__init__(name, *args, **kargs) def _get_mode(self): return self._mode def _set_mode(self, mode): if mode and mode.lower() not in ('r', 'w', 'rw'): str_err = _("Mode type: {0} not supported ('r', 'w','rw')") raise ValueError(str_err.format(mode)) self._mode = mode mode = property(fget=_get_mode, fset=_set_mode, doc="Set or obtain the opening mode of raster") def __setitem__(self, key, row): """Return the row of Raster object, slice allowed.""" if isinstance(key, slice): #Get the start, stop, and step from the slice return [ self.put_row(ii, row) for ii in range(*key.indices(len(self))) ] elif isinstance(key, tuple): x, y = key return self.put(x, y, row) elif isinstance(key, int): if key < 0: # Handle negative indices key += self._rows if key >= self._rows: raise IndexError(_("Index out of range: %r.") % key) return self.put_row(key, row) else: raise TypeError("Invalid argument type.") @must_be_open def map2segment(self): """Transform an existing map to segment file. """ row_buffer = Buffer((self._cols), self.mtype) for row in range(self._rows): libraster.Rast_get_row(self._fd, row_buffer.p, row, self._gtype) self.segment.put_row(row, row_buffer) @must_be_open def segment2map(self): """Transform the segment file to a map. """ row_buffer = Buffer((self._cols), self.mtype) for row in range(self._rows): row_buffer = self.segment.get_row(row, row_buffer) libraster.Rast_put_row(self._fd, row_buffer.p, self._gtype) @must_be_open def get_row(self, row, row_buffer=None): """Return the row using the `segment.get_row` method :param row: specify the row number :type row: int :param row_buffer: specify the Buffer object that will be instantiate :type row_buffer: Buffer object >>> elev = RasterRowIO(test_raster_name) >>> elev.open('r') >>> for row in elev: ... row Buffer([11, 21, 31, 41], dtype=int32) Buffer([12, 22, 32, 42], dtype=int32) Buffer([13, 23, 33, 43], dtype=int32) Buffer([14, 24, 34, 44], dtype=int32) >>> elev.close() >>> with RasterSegment(test_raster_name) as elev: ... for row in elev: ... row Buffer([11, 21, 31, 41], dtype=int32) Buffer([12, 22, 32, 42], dtype=int32) Buffer([13, 23, 33, 43], dtype=int32) Buffer([14, 24, 34, 44], dtype=int32) """ if row_buffer is None: row_buffer = Buffer((self._cols), self.mtype) return self.segment.get_row(row, row_buffer) @must_be_open def put_row(self, row, row_buffer): """Write the row using the `segment.put_row` method :param row: a Row object to insert into raster :type row: Buffer object Input and output must have the same type in case of row copy >>> map_a = RasterSegment(test_raster_name) >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_a.open('r') >>> map_b.open('w', mtype="CELL", overwrite=True) >>> for row in xrange(map_a.info.rows): ... map_b[row] = map_a[row] + 1000 >>> map_a.close() >>> map_b.close() >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_b.open("r") >>> for row in map_b: ... row Buffer([1011, 1021, 1031, 1041], dtype=int32) Buffer([1012, 1022, 1032, 1042], dtype=int32) Buffer([1013, 1023, 1033, 1043], dtype=int32) Buffer([1014, 1024, 1034, 1044], dtype=int32) >>> map_b.close() """ self.segment.put_row(row, row_buffer) @must_be_open def get(self, row, col): """Return the map value using the `segment.get` method :param row: Specify the row number :type row: int :param col: Specify the column number :type col: int >>> elev = RasterSegment(test_raster_name) >>> elev.open('r') >>> for i in xrange(4): ... elev.get(i,i) 11 22 33 44 >>> elev.close() >>> with RasterSegment(test_raster_name) as elev: ... elev.get(0,0) ... elev.get(1,1) ... elev.get(2,2) ... elev.get(3,3) 11 22 33 44 """ return self.segment.get(row, col) @must_be_open def put(self, row, col, val): """Write the value to the map using the `segment.put` method :param row: Specify the row number :type row: int :param col: Specify the column number :type col: int :param val: Specify the value that will be write to the map cell :type val: value >>> map_a = RasterSegment(test_raster_name) >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_a.open('r') >>> map_b.open('w', mtype="FCELL", overwrite=True) >>> for row in xrange(map_a.info.rows): ... for col in xrange(map_a.info.cols): ... value = map_a.get(row,col) ... map_b.put(row,col,value + 100) >>> map_a.close() >>> map_b.close() >>> map_b = RasterSegment(test_raster_name + "_segment") >>> map_b.open("r") >>> for row in map_b: ... row Buffer([ 111., 121., 131., 141.], dtype=float32) Buffer([ 112., 122., 132., 142.], dtype=float32) Buffer([ 113., 123., 133., 143.], dtype=float32) Buffer([ 114., 124., 134., 144.], dtype=float32) >>> map_b.close() """ self.segment.val.value = val self.segment.put(row, col) def open(self, mode=None, mtype=None, overwrite=None): """Open the map, if the map already exist: determine the map type and copy the map to the segment files; else, open a new segment map. :param mode: specify if the map will be open with read, write or read/write mode ('r', 'w', 'rw') :type mode: str :param mtype: specify the map type, valid only for new maps: CELL, FCELL, DCELL :type mtype: str :param overwrite: use this flag to set the overwrite mode of existing raster maps :type overwrite: bool """ # read rows and cols from the active region self._rows = libraster.Rast_window_rows() self._cols = libraster.Rast_window_cols() self.mode = mode if mode else self.mode self.mtype = mtype if mtype else self.mtype self.overwrite = overwrite if overwrite is not None else self.overwrite if self.exist(): self.info.read() self.cats.mtype = self.mtype self.cats.read() self.hist.read() if ((self.mode == "w" or self.mode == "rw") and self.overwrite is False): str_err = _("Raster map <{0}> already exists. Use overwrite.") fatal(str_err.format(self)) # We copy the raster map content into the segments if self.mode == "rw" or self.mode == "r": self._fd = libraster.Rast_open_old(self.name, self.mapset) self._gtype = libraster.Rast_get_map_type(self._fd) self.mtype = RTYPE_STR[self._gtype] # initialize the segment, I need to determine the mtype of the # map # before to open the segment self.segment.open(self) self.map2segment() self.segment.flush() self.cats.read() self.hist.read() if self.mode == "rw": #warning(_(WARN_OVERWRITE.format(self))) # Close the file descriptor and open it as new again libraster.Rast_close(self._fd) self._fd = libraster.Rast_open_new(self.name, self._gtype) # Here we simply overwrite the existing map without content copying elif self.mode == "w": #warning(_(WARN_OVERWRITE.format(self))) self._gtype = RTYPE[self.mtype]['grass type'] self.segment.open(self) self._fd = libraster.Rast_open_new(self.name, self._gtype) else: if self.mode == "r": str_err = _("Raster map <{0}> does not exist") raise OpenError(str_err.format(self.name)) self._gtype = RTYPE[self.mtype]['grass type'] self.segment.open(self) self._fd = libraster.Rast_open_new(self.name, self._gtype) @must_be_open def close(self, rm_temp_files=True): """Close the map, copy the segment files to the map. :param rm_temp_files: if True all the segments file will be removed :type rm_temp_files: bool """ if self.mode == "w" or self.mode == "rw": self.segment.flush() self.segment2map() if rm_temp_files: self.segment.close() else: self.segment.release() libraster.Rast_close(self._fd) # update rows and cols attributes self._rows = None self._cols = None self._fd = None