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

7

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!!
    – JWB
    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.
    – user2856
    Oct 27, 2022 at 22:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.