Python Rasterio – Fix GeoJSON Masking Issue

clipgeojsonmaskingpythonrasterio

I'm trying to load GeoJSON from a file for use with rasterio mask on a GeoTIFF and I can't seem to get the GeoJSON to load properly. I get this error:

File "/Users/user/example.py", line 18, in clip
out_image, out_transform = mask(src, geoms, crop=True)

File "/usr/local/lib/python2.7/site-packages/rasterio/tools/mask.py", line 12, in mask
return rasterio.mask.mask(*args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/rasterio/mask.py", line 57, in mask
all_bounds = [rasterio.features.bounds(shape) for shape in shapes]

File "/usr/local/lib/python2.7/site-packages/rasterio/features.py", line 325, in bounds
geom = geometry.get('geometry') or geometry
AttributeError: 'unicode' object has no attribute 'get' 

Here is the code:

#!/usr/bin/env python

import json
import rasterio
from rasterio.tools.mask import mask

class example:
    def __init__(self, tile_dir):
        self.tile_dir = tile_dir

    def clip(self):
        with open(self.tile_dir + "/geo.json") as data_file:
            geoms= json.loads(data_file.read())
        print type(geoms)
        # load the raster, mask it by the polygon and crop it
        with rasterio.open(self.tile_dir + "/tile.tif") as src:
            out_image, out_transform = mask(src, geoms, crop=True)
        out_meta = src.meta.copy()

        # save the resulting raster
        out_meta.update({"driver": "GTiff",
            "height": out_image.shape[1],
            "width": out_image.shape[2],
            "transform": out_transform})

        with rasterio.open(self.tile_dir + "/clipped.tif", "w", **out_meta) as dest:
            dest.write(out_image)

Any ideas? I've also tried doing this instead, but it results in the same error…

geoms= json.load(data_file)

Best Answer

If your GeoJSON geometry is unique (not a "type": "FeatureCollection") as in

geoms = {'type': 'Polygon', 'coordinates': [[(250542.40328375285, 141691.07089614146), (250641.30366207045, 141400.7504307576), (250421.17056194422, 141512.41214821293), (250542.40328375285, 141691.07089614146)]]}

and you try

with rasterio.open("a.tif") as src:
     out_image, out_transform = mask(src, geoms, crop=True)   

The result is AttributeError: 'unicode' object has no attribute 'get'

Why ?

If you examine the Source code for rasterio.mask and the Rasterio Cookbook : Masking raster with a polygon feature files we can see that shapes is a list of polygons

def mask(raster, shapes, nodata=None, crop=False, all_touched=False,invert=False):
    """ 
    ....
     Parameters
     shapes: list of polygons
     ....
     """
     ....
     all_bounds = [rasterio.features.bounds(shape) for shape in shapes]
     ....

And in the Cookbook (list of geometries):

    geoms = [feature["geometry"] for feature in shapefile]

Therefore you can

1) use a list

geoms = list(geoms) 
# or directly
geoms = [{'type': 'Polygon', 'coordinates': [[(250542.40328375285, 141691.07089614146), (250641.30366207045, 141400.7504307576), (250421.17056194422, 141512.41214821293), (250542.40328375285, 141691.07089614146)]]}]

2) or modify the script

all_bounds = [rasterio.features.bounds(geom)]
Related Question