[GIS] Store bands in temporary file Rasterio

in-memoryrasterio

As I'm using multiple functions in one process, I would like to pass results of each function to the next one using an In-memory File. I'm using Rasterio and I saw that there is a way to create In-memory files in the documentation, but unfortunately it seems like it's not working like usual files. I cannot use open(temporaryfile).meta.copy() to get infos (GTIFF in my case) of the file.

Is there a way to correctly store everything as in a Gtiff file but in a memory file or do I have to process in another way ?

Best Answer

You may pass instances of MemoryFile or datasets opened from them to functions. For example:

>>> def print_metadata(dataset):
...     print(dataset.profile)
...
>>> from rasterio.io import MemoryFile
>>> tif_bytes = open('/Users/seang/code/rasterio/tests/data/RGB.byte.tif', 'rb').read()
>>> with MemoryFile(tif_bytes) as memfile:
...     with memfile.open() as dataset:
...         print_metadata(dataset)
...
{'driver': 'GTiff', 'dtype': 'uint8', 'nodata': 0.0, 'width': 791, 'height': 718, 'count': 3, 'crs': CRS({'init': 'epsg:32618'}), 'transform': Affine(300.0379266750948, 0.0, 101985.0,
   0.0, -300.041782729805, 2826915.0), 'tiled': False, 'interleave': 'pixel'}

Note well that when the idented with block ends, the in-memory file is deleted. This is to give you control over memory allocation on your computer. The Rasterio dataset object is also closed at this point.

>>> dataset.closed
True
>>> memfile.open()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/seang/envs/rio-blog-post/lib/python3.6/site-packages/rasterio/env.py", line 305, in wrapper
    return f(*args, **kwds)
  File "/Users/seang/envs/rio-blog-post/lib/python3.6/site-packages/rasterio/io.py", line 112, in open
    raise IOError("I/O operation on closed file.")
OSError: I/O operation on closed file.

If you pass them to functions after this, they can't be operated on. Keep your memory file open in your main program and all will be fine.