Commit 1a5d75ed authored by Hoek, Steven's avatar Hoek, Steven
Browse files

Introduction of a new class which can help to manage data retrieved as tiles

parent 9acc312a
# -*- coding: latin-1 -*-
# Copyright (c) 2004-2020 WUR, Wageningen
"""TileLib - a Python library for tiling raster data"""
from ..formats.gridenvelope2d import GridEnvelope2D
from ..formats.raster import Raster
from ..formats.inmemoryraster import InMemoryRaster
from ..toolbox.striplib import StripManager
from ..formats.const import constants as const
__author__ = "Steven B. Hoek"
class TileManager():
'''
Class that retrieves enough rows of data from a given raster grid to obtain a strip
with a given number of rows; then from that strip it produces tiles - also as a raster grid.
Tiles are returned in the following order: from left to right and from top to bottom.
'''
# Default settings
__depth = 1
__width = 1
__curcol = 0
__curstrip = None
__stripmanager = None
__rowoffset = 0 # row offset
__coloffset = 0 # column offset
__rowoverlap = 0
__coloverlap = 0
def __init__(self, rg, tilewidth, tileheight, coloverlap=0, rowoverlap=0):
# Check the inputs
if not isinstance(rg, Raster):
raise TypeError("Input is not a raster!")
if not isinstance(rg, GridEnvelope2D):
raise TypeError("Input is not a grid envelope!")
# Assume: rg is a raster grid with an open file at position 0
self.__rg = rg
self.__xll = rg.xll
self.__yll = rg.yll
self.__ncols = rg.ncols
self.__nrows = rg.nrows
self.__datatype = rg.datatype
self.__curcol = 0
self.__stripmanager = StripManager(rg, tileheight)
self.__stripmanager.stripheight = tileheight
self.__depth = tileheight
self.__width = tilewidth
self.__rowoverlap = rowoverlap
self.__coloverlap = coloverlap
# Get the first strip ready
self.nextstrip()
def __iter__(self):
return TileIterator(self)
def next(self):
'''Returns a tile with number of rows and columns'''
# TODO: implement the option to have row and column offsets
result = None
if self.__curcol + self.__width > self.__ncols:
width = self.__ncols - self.__curcol
else:
width = self.__width
if (width > 0) and (not self.__curstrip is None):
# In case buffer contains rows, prepare to add them at the beginning of the output raster
width += self.__coloverlap
xll = self.__xll + (self.__curcol * self.__rg.dx)
data = self.__curstrip.data[:, self.__curcol:self.__curcol+width]
imr = InMemoryRaster("dummy_file.ext", data, self.__datatype)
width = min(width, len(data[0]))
height = self.__curstrip.nrows
imr.open('w', width, height, xll, self.__yll, self.__rg.dy, self.__rg.nodatavalue)
self.__curcol += self.__width
result = imr
return result
def nextstrip(self):
# Initialise
result = False
rowbuf = None
try:
# If there's row overlap, keep the last few lines of the strip in a buffer
if (self.__rowoverlap > 0) and (not self.__curstrip is None):
rowbuf = self.__curstrip.data[-1 * self.__rowoverlap:, :]
self.__curstrip = self.__stripmanager.next(rowbuf, self.__rowoverlap)
self.__curcol = 0
result = True
except:
raise StopIteration
finally:
return result
def close(self):
self.__rg = None
self.__initialised = False
@property
def tileheight(self):
return self.__depth
@tileheight.setter
def tileheight(self, tileheight):
# TODO: differentiate dx and dy!
self.__depth = tileheight
self.__stripmanager.stripheight = tileheight
@property
def tilewidth(self):
return self.__width
@tilewidth.setter
def tilewidth(self, tilewidth):
# TODO: differentiate dx and dy!
self.__width = tilewidth
@property
def rowoffset(self):
return self.__rowoffset
@rowoffset.setter
def rowoffset(self, rowoffset):
self.__rowoffset = rowoffset
@property
def coloffset(self):
return self.__coloffset
@coloffset.setter
def coloffset(self, coloffset):
self.__coloffset = coloffset
@property
def curcol(self):
return self.__curcol
@property
def ncols(self):
return self.__ncols
@property
def rowoverlap(self):
return self.__rowoverlap
class TileIterator:
def __init__(self, tilemanager):
self.__tilemanager = tilemanager
def __next__(self):
# Initialise
result = None
# Determine whether another tile can be obtained from the current strip
curcol = self.__tilemanager.curcol
width = self.__tilemanager.tilewidth
ncols = self.__tilemanager.ncols
tilesleft = (ncols - curcol) // width
if tilesleft > 0:
result = self.__tilemanager.next()
else:
# Try to see whether a new strip is available
if self.__tilemanager.nextstrip():
result = self.__tilemanager.next()
else:
raise StopIteration
return result
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment