I ran into this issue so I wrote an iterator class to do this. In my case I wanted to return the X,Y,Z values but you could easily modify to return the numpy array.
It can be used simply like this:
for block in RasterBlockIterator(raster, no_data_val=self.no_data_val):
for point in block:
x = point[0]
y = point[1]
z = point[2]
The iterator class. If you want the numpy array just return the arr on line 62. By default it works in blocks of 1000*1000
class RasterBlockIterator:
"""Iterator that extracts tiles of data from a Esri Raster."""
def __init__(self, raster: arcpy.Raster, tile_size=(1000, 1000), no_data_val=np.nan):
"""
:param raster: Raster to iterate
:param tile_size: size of each block/tile to extrac to numpy array
:param no_data_val: value in the raster which should be treated as no data
"""
self.tile_size = tile_size
self.raster = raster
self.no_data_val = no_data_val
self.cell_size = raster.meanCellHeight
self.pos = 0
t_rows = raster.height
t_cols = raster.width
x_min = raster.extent.XMin
y_min = raster.extent.YMin
self.tiles = []
for row in range(0, t_rows, tile_size[1]):
for col in range(0, t_cols, tile_size[0]):
colend = min([t_cols, col + tile_size[0]])
rowend = min([t_rows, row + tile_size[1]])
xstart = x_min + (col * self.cell_size)
ystart = y_min + (row * self.cell_size)
self.tiles.append(namedtuple('tile', 'colstart colend rowstart rowend xstart ystart')(
colstart=col,
colend=colend,
rowstart=row,
rowend=rowend,
xstart=xstart,
ystart=ystart
))
def __iter__(self):
return self
def __len__(self):
return len(self.tiles)
def __next__(self) -> List[Tuple[float, float, float]]:
try:
tile = self.tiles[self.pos]
except IndexError:
raise StopIteration
lower_l = arcpy.Point(tile.xstart, tile.ystart)
ncols = tile.colend - tile.colstart
rnrows = tile.rowend - tile.rowstart
arr = arcpy.RasterToNumPyArray(self.raster, nodata_to_value=np.nan,
lower_left_corner=lower_l,
ncols=ncols, nrows=rnrows)
output_data = [
(j * self.cell_size + tile.xstart, i * self.cell_size + tile.ystart, value)
for i, row in enumerate(arr)
for j, value in enumerate(row)
if not self.no_data_val == value and not np.isnan(value)
]
self.pos += 1
return output_data
```