TypeError: invalid driver when writing Rasterio created mosaic of Sentinel JP2’s

jpeg 2000pythonrasteriosentinel-2

The code below represents my attempt at mosaicing sentinel bands. I get an error right at the end when trying to write the mosaics. It states:

TypeError: invalid driver: {'driver': 'GTiff', 'dtype': 'uint16',
'nodata': None, 'width': 20982, 'height': 20982, 'count': 1, 'crs':
'EPSG:32610', 'transform': Affine(20.0, 0.0, 499980.0,
0.0, -20.0, 6400020.0)}

import rasterio
from rasterio.merge import merge
from rasterio.plot import show
import glob
import os


# Folder and File Paths

# location of sentinel images
dirpath = r"C:\Users\Matthew\OneDrive\Land Suitability Model\Layers\Sentinel\Sentinel RST"

# # Print metadata from sentinel image set
# single raster_path = r"C:\Users\Matthew\OneDrive \Land Suitability Model\Layers\Sentinel\Sentinel RST\T10VFH_B04.jp2"
# with rasterio.open(raster_path, "r", driver="JP2OpenJPEG") as test:
#     raster_meta = test.meta
#     print(raster_meta)
    
# Location of moasaic output files
output_b2 = r"C:\Users\Matthew\OneDrive \Land Suitability Model\Layers\Sentinel\Sentinel RST\mosaic_b2.tif"
output_b4 = r"C:\Users\Matthew\OneDrive \Land Suitability Model\Layers\Sentinel\Sentinel RST\mosaic_b4.tif"
output_b5 = r"C:\Users\Matthew\OneDrive \Land Suitability Model\Layers\Sentinel\Sentinel RST\mosaic_b5.tif"
output_b6 = r"C:\Users\Matthew\OneDrive \Land Suitability Model\Layers\Sentinel\Sentinel RST\mosaic_b6.tif"

# Search for all jp2 images in directory & glob images to a list
b2_images = "*_B02.jp2"
b4_images = "*_B04.jp2"
b5_images = "*_B05.jp2"
b6_images = "*_B06.jp2"

images_b2 = os.path.join(dirpath, b2_images)
images_b4 = os.path.join(dirpath, b4_images)
images_b5 = os.path.join(dirpath, b5_images)
images_b6 = os.path.join(dirpath, b6_images)

image_list_b2 = glob.glob(images_b2)
image_list_b4 = glob.glob(images_b4)
image_list_b5 = glob.glob(images_b5)
image_list_b6 = glob.glob(images_b6)

images
image_list

# Mosaic B2, B4, B5, B6 images
# Put band images in list then open images using raterio function  
b2_images_to_mosaic = []
b4_images_to_mosaic = []
b5_images_to_mosaic = []
b6_images_to_mosaic = []

for b2_images in image_list_b2:
    sentinel_b2 = rasterio.open(b2_images)
    b2_images_to_mosaic.append(sentinel_b2)

for b4_images in image_list_b4:
    sentinel_b4 = rasterio.open(b4_images)
    b4_images_to_mosaic.append(sentinel_b4)

for b5_images in image_list_b5:
    sentinel_b5 = rasterio.open(b5_images)
    b5_images_to_mosaic.append(sentinel_b5)

for b6_images in image_list_b6:
    sentinel_b6 = rasterio.open(b6_images)
    b6_images_to_mosaic.append(sentinel_b6)
                
# Use merge function to create B2,B4,B5,B6 image mosaic

B2_mosaic, out_trans_b2 = merge(b2_images_to_mosaic)
B4_mosaic, out_trans_b4 = merge(b4_images_to_mosaic)
B5_mosaic, out_trans_b5 = merge(b5_images_to_mosaic)
B6_mosaic, out_trans_b6 = merge(b6_images_to_mosaic)

# Show mosaic's to view results

show(B2_mosaic, cmap='viridis')
show(B4_mosaic, cmap='viridis')
show(B5_mosaic, cmap='viridis')
show(B6_mosaic, cmap='viridis')

# Copy metadata for each band
b2_out_meta = sentinel_b2.meta.copy()
b4_out_meta = sentinel_b4.meta.copy()
b5_out_meta = sentinel_b5.meta.copy()
b6_out_meta = sentinel_b6.meta.copy()

mosaic_crs = 'EPSG:32610'

b2_out_meta.update({"driver": "GTiff",
                  "height": B2_mosaic.shape[1],
                  "width": B2_mosaic.shape[2],
                  "transform": out_trans_b2,
                  "crs": mosaic_crs
                  })
b4_out_meta.update({"driver": "GTiff",
                  "height": B4_mosaic.shape[1],
                  "width": B4_mosaic.shape[2],
                  "transform": out_trans_b4,
                  "crs": mosaic_crs
                  })
b5_out_meta.update({"driver": "GTiff",
                  "height": B5_mosaic.shape[1],
                  "width": B5_mosaic.shape[2],
                  "transform": out_trans_b5,
                 "crs": mosaic_crs
                  })
b6_out_meta.update({"driver": "GTiff",
                  "height": B6_mosaic.shape[1],
                  "width": B6_mosaic.shape[2],
                  "transform": out_trans_b6,
                  "crs": mosaic_crs
                  })
# Write mosaics to disk
with rasterio.open(output_b2, "w", **b2_out_meta) as dst:
    dst.write(B2_mosaic)   

Best Answer

You're passing a dict to rasterio.open as the driver argument. Either pass them all as named arguments or use **dict unpacking:

Instead of:

with rasterio.open(output_b2, "w", b2_out_meta) as dst:

Use:

with rasterio.open(output_b2, "w", **b2_out_meta) as dst:

Or

with rasterio.open(output_b2, "w", driver='GTiff', dtype='uint16', etc...) as dst: