5

I'm trying to optimize my code a bit because I'm tired of having intermediate files. I use rasterio to reproject grib files in the following manner:

def reproject_raster(in_path, out_path):
    # reproject raster to project crs
    with rio.open(in_path) as src:
        src_crs = src.crs
        transform, width, height = calculate_default_transform(src_crs, crs, src.width, src.height, *src.bounds)
        kwargs = src.meta.copy()

        kwargs.update({
            'crs': crs,
            'transform': transform,
            'width': width,
            'height': height})

        with rio.open(out_path, 'w', **kwargs) as dst:
            for i in range(1, src.count + 1):
                reproject(
                    source=rio.band(src, i),
                    destination=rio.band(dst, i),
                    src_transform=src.transform,
                    src_crs=src.crs,
                    dst_transform=transform,
                    dst_crs=crs,
                    resampling=Resampling.nearest)
    return(out_path)

Does anyone know how to do this in-memory so that the function would return something like a rasterio <class 'rasterio.io.DatasetReader'> type instead of saving it to a file?

1

1 Answer 1

8

You could use a MemoryFile

Something like:

from contextlib import contextmanager  
import rasterio as rio
from rasterio.io import MemoryFile

@contextmanager  
def reproject_raster(in_path, crs):
    # reproject raster to project crs
    with rio.open(in_path) as src:
        src_crs = src.crs
        transform, width, height = calculate_default_transform(src_crs, crs, src.width, src.height, *src.bounds)
        kwargs = src.meta.copy()

        kwargs.update({
            'crs': crs,
            'transform': transform,
            'width': width,
            'height': height})

        with MemoryFile() as memfile:
            with memfile.open(**kwargs) as dst:
                for i in range(1, src.count + 1):
                    reproject(
                        source=rio.band(src, i),
                        destination=rio.band(dst, i),
                        src_transform=src.transform,
                        src_crs=src.crs,
                        dst_transform=transform,
                        dst_crs=crs,
                        resampling=Resampling.nearest)
            with memfile.open() as dataset:  # Reopen as DatasetReader
                yield dataset  # Note yield not return as we're a contextmanager

with reproject_raster(in_path, crs) as in_mem_ds:
    # do something with in_mem_ds
2
  • yes, this works! I was missing the @contextmanager wrapper. Still not sure why i need that, but i can look into it. Thank you!! Commented Oct 27, 2022 at 21:30
  • 2
    @JWB I've set up the reproject_raster as a contextmanager so you can use it in a with block (just like with rio.open(somefile) as src:). This means the memfile gets closed and cleaned up automatically when you exit the with block. It's not necessary, just good practice. Commented Oct 27, 2022 at 22:22

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.