8 votos

Abrir un archivo raster con permisos de lectura y escritura en rasterio

Estoy tratando de escribir una función que me ayude a construir un archivo de memoria de rasterio y devuelva el objeto lector de conjunto de datos para poder manipularlo según sea necesario. Estoy tratando de evitar las declaraciones with porque me gustaría permitir al usuario leer y escribir según lo consideren necesario. Hasta ahora tengo esto:

from rasterio import mask, features, warp
from rasterio.io import MemoryFile
import rasterio
import numpy as np

def create_memory_file(data, west_bound, north_bound, cellsize, driver='AAIGrid'):
    # data es un array de numpy
    dtype = data.dtype
    shape = data.shape
    transform = rasterio.transform.from_origin(west_bound, north_bound, cellsize, cellsize)
    memfile = MemoryFile()
    dataset = memfile.open(driver=driver, width= shape[1], height = shape[0], transform=transform, count=1, dtype = dtype)
    dataset.write(data,1)

    return dataset
def close_memory_file(memfile):
    memfile.close()

data = np.array([[1,2,3], [4,5,6], [7,8,9]])
memfile = create_memory_file(data, 0, 2, 0.5)
memfile.read(1)

La última línea arroja un error:

Traceback (most recent call last):
  File "D:/11202750-002_RA2CE/Basis/common.py", line 214, in 
    memfile.read(1)
  File "rasterio\_io.pyx", line 209, in rasterio._io.DatasetReaderBase.read
rasterio.errors.UnsupportedOperation: not readable

Aparentemente, el memfile solo tiene permisos de escritura debido a lo siguiente:

>>> memfile

>>> memfile.mode
'w'

He probado varias combinaciones de agregar mode=r+, permissions=r+ a mi llamada a memfile.open() pero no lo permite.

¿Cómo puedo agregar el modo de lectura/escritura en el nivel de la declaración open?

0 votos

¿Cuál fue exactamente tu error con "mode=r+"?

0 votos

Llamar con dataset = memfile.open(mode='r+', driver=driver, width=shape[1], height=shape[0], transform=transform, count=1, dtype=dtype) genera el siguiente error de tipo: TypeError: __init__() recibió múltiples valores para el argumento de palabra clave 'mode'

0 votos

No estoy seguro de que esto sea posible. La forma habitual es escribir y cerrar, luego leer. Si desea escribir nuevamente, simplemente sobrescriba el objeto del archivo de memoria.

7voto

Lucas Puntos 128

En rasterio <= 1.0.7 esto no es posible. Debes escribir y cerrar, luego leer. Si deseas volver a escribir, simplemente sobrescribe el objeto memfile.

Por ejemplo:

from rasterio.io import MemoryFile
import rasterio
import numpy as np

def create_memory_file(data, west_bound, north_bound, cellsize, driver='GTIFF'):
    #data es una matriz numpy
    if data.ndim ==2: # Manejar arreglos de entrada de 2 o 3D
        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()  # <==== Reabrir el 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())

Salida:

[[[1 2 3]
  [4 5 6]
  [7 8 9]]]

[[[ 4  5  6]
  [ 7  8  9]
  [10 11 12]]]

A partir de rasterio 1.0.8 puedes escribir y leer ya que los conjuntos de datos en un MemoryFile se abren en modo r+/w+. Ten en cuenta que el controlador subyacente de GDAL necesita admitir la creación de un nuevo conjunto de datos desde cero no solo la creación de una copia de un conjunto de datos existente.

Por ejemplo:

from rasterio.io import MemoryFile
import rasterio
import numpy as np

def create_memory_file(data, west_bound, north_bound, cellsize, driver='GTIFF'):
    #data es una matriz numpy
    if data.ndim ==2: # Manejar arreglos de entrada de 2 o 3D
        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()) 

Salida:

[[[1 2 3]
  [4 5 6]
  [7 8 9]]]

[[[ 4  5  6]
  [ 7  8  9]
  [10 11 12]]]

0 votos

Había optado por una solución similar, pero creo que esta es mejor. No sabía que se podía devolver cosas desde el interior con declaraciones en una función. buen trabajo. ¿Tengo que preocuparme por cerrar el archivo?

1 votos

@user32882 no, se recogerá la basura cuando salga del ámbito. Acabo de ejecutar un bucle de 10,000 iteraciones con una matriz grande y el uso de memoria no aumentó. Nota: He editado la función en mi respuesta para manejar matrices 2 y 3D.

1 votos

@user32882 ver también edición sobre el soporte de r+ en rasterio 1.0.8

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X