Reading Rasters by block can be done in rasterio and I'd argue it's easier than in GDAL. There is even a tutorial on windowed read/write over at GitHub.
Let's take a look at the read
functions arguments, which allows you to set a window to read data from:
def read(self, indexes=None, out=None, window=None, masked=False,
boundless=False):
"""Read raster bands as a multidimensional array
Parameters
----------
window : a pair (tuple) of pairs of ints, optional
The optional `window` argument is a 2 item tuple. The first
item is a tuple containing the indexes of the rows at which
the window starts and stops and the second is a tuple
containing the indexes of the columns at which the window
starts and stops. For example, ((0, 2), (0, 2)) defines
a 2x2 window at the upper left of the raster dataset.
"""
So all you need now is a way to create the window tuples. That's what rasterios block_windows
function is for:
def block_windows(self, bidx=0):
"""Returns an iterator over a band's block windows and their
indexes.
[....]
The primary use of this function is to obtain windows to pass to
read_band() for highly efficient access to raster block data.
"""
So in your case I guess the code would look something like this:
with rasterio.open("your/data/geo.tif") as src:
for block_index, window in src.block_windows(1):
block_array = src.read(window=window)
result_block = some_calculation(block_array)
In rasterio
<= 1.0.7 this is not possible. You have to write and close, then read. If you want to write again, just overwrite the memfile
object.
For example:
from rasterio.io import MemoryFile
import rasterio
import numpy as np
def create_memory_file(data, west_bound, north_bound, cellsize, driver='GTIFF'):
#data is a numpy array
if data.ndim ==2: # Handle 2 or 3D input arrays
data = np.expand_dims(data, axis=0)
dtype = data.dtype
shape = data.shape
transform = rasterio.transform.from_origin(west_bound, north_bound, cellsize, cellsize)
with MemoryFile() as memfile:
with memfile.open(
driver=driver, width= shape[2], height = shape[1],
transform=transform, count=shape[0], dtype=dtype) as dataset:
dataset.write(data)
return memfile.open() # <==== Re-open the memfile
data = np.array([[1,2,3], [4,5,6], [7,8,9]]).astype(np.int32)
memfile = create_memory_file(data, 0, 2, 0.5)
print(memfile.read())
data = np.array([[4,5,6], [7,8,9], [10,11, 12]]).astype(np.int32)
memfile = create_memory_file(data, 0, 2, 0.5)
print(memfile.read())
Output:
[[[1 2 3]
[4 5 6]
[7 8 9]]]
[[[ 4 5 6]
[ 7 8 9]
[10 11 12]]]
As of rasterio
1.0.8 you can write and read as datasets in a MemoryFile
are opened in r+
/w+
mode. Note that the underlying GDAL driver needs to support creation of a new dataset from scratch not just creation of a copy of an existing dataset.
For example:
from rasterio.io import MemoryFile
import rasterio
import numpy as np
def create_memory_file(data, west_bound, north_bound, cellsize, driver='GTIFF'):
#data is a numpy array
if data.ndim ==2: # Handle 2 or 3D input arrays
data = np.expand_dims(data, axis=0)
dtype = data.dtype
shape = data.shape
transform = rasterio.transform.from_origin(west_bound, north_bound, cellsize, cellsize)
with MemoryFile() as memfile:
dataset = memfile.open(
driver=driver, width= shape[2], height = shape[1],
transform=transform, count=shape[0], dtype=dtype)
dataset.write(data)
return dataset
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.int32)
memfile = create_memory_file(data, 0, 2, 0.5)
print(memfile.read())
data = np.array([[4, 5, 6], [7, 8, 9], [10, 11, 12]]).astype(np.int32)
memfile.write(data, 1)
print(memfile.read())
Output:
[[[1 2 3]
[4 5 6]
[7 8 9]]]
[[[ 4 5 6]
[ 7 8 9]
[10 11 12]]]
Best Answer
I tried with the following and it worked fine: