Examples on how to use python libraries to access and use COGs. Demonstrating one of the cloud
optimized advantages, being able to access a portion of the data without having to download the entire file.
importpystac_clientimportrasterio# Define a bounding box for an AOI (Ottawa) in EPSG:4326bbox=[-75.8860,45.3157,-75.5261,45.5142]bbox_crs="EPSG:4326"# Link to ccmeo datacube stac-apistac_root="https://datacube.services.geo.ca/stac/api"catalog=pystac_client.Client.open(stac_root)search=catalog.search(collections=['mrdem-30'],bbox=bbox,)# Get the link to the data asset for mrdem-30 dtmlinks=[]forpageinsearch.pages():foriteminpage:links.append(item.assets['dtm'].href)# Read the header of a remote COG withrasterio.open(links[0])assrc:# Read the header of a COGprint(src.tags())# >> {'AREA_OR_POINT': 'Area', # 'TIFFTAG_DATETIME': '2024:06:13 12:00:00'}print(src.profile)# >> {'driver': 'GTiff', 'dtype': 'float32', 'nodata': -32767.0, # 'width': 183687, 'height': 159655, 'count': 1, # 'crs': CRS.from_epsg(3979), 'transform': Affine(30.0, 0.0, # -2454000.0, 0.0, -30.0, 3887400.0), 'blockxsize': 512, # 'blockysize': 512, 'tiled': True, 'compress': 'lzw', # 'interleave': 'band'}
For this example, you will need to also install shapely:
pipinstallshapely
In this code you will :
Query a STAC API with pystac-client to get link to a COG;
Read a portion of a remote COG based on an AOI with the window functionality;
Write the portion locally inside a .tif file (Optional)
Info
This specific example uses the collection mrdem-30 from CCMEO's datacube
Tip
COG'S file contains internal tiling that can be leverage by iterating on
the src.block_windows() while reading. If the reading window does not align with
the internal tiling of the file, the data will be resampled.
importpystac_clientimportrasteriofromrasterio.windowsimportfrom_boundsfromrasterio.warpimporttransform_geomfromshapely.geometryimportbox,shape# Define a bounding box for an AOI (Ottawa) in EPSG:4326bbox=[-75.8860,45.3157,-75.5261,45.5142]bbox_crs="EPSG:4326"# Link to ccmeo datacube stac-apistac_root="https://datacube.services.geo.ca/stac/api"catalog=pystac_client.Client.open(stac_root)search=catalog.search(collections=['mrdem-30'],bbox=bbox,)# Get the link to the data asset for mrdem-30 dtmlinks=[]forpageinsearch.pages():foriteminpage:links.append(item.assets['dtm'].href)# Read AOI from the first COGwithrasterio.open(links[0])assrc:# Transform bbox to src EPSGtransformed_bbox=shape(transform_geom(src.crs,bbox_crs,box(*bbox))).bounds# Define the window to read the valueswindow=from_bounds(transformed_bbox[0],transformed_bbox[1],transformed_bbox[2],transformed_bbox[3],src.transform)# Read value from filerst=src.read(1,window=window)# Copy and update the source metadata to write the output tiffmetadata=src.meta.copy()metadata.update({'height':window.height,'width':window.width,'transform':rasterio.windows.transform(window,src.transform)})# Perform analysis ...# (Optional) Write the output array to a tiff fileoutput_tiff=r"path/to/output.tif"withrasterio.open(output_tiff,'w',**metadata)asdst:dst.write(rst,1)
importpystac_clientimportrasterioimportpyprojfromshapely.geometryimportPointfromshapely.opsimporttransform# Define the coordinate of the point of interest in EPSG:4326 (for the request to the STAC API)lonlat=Point(-104.898838,69.232434)# Modify the projection of the point (for the COG extraction)proj=pyproj.Transformer.from_crs(4326,3979,always_xy=True)point=transform(proj.transform,lonlat)x1,y1=point.coords.xy# Link to ccmeo datacube stac-apistac_root="https://datacube.services.geo.ca/stac/api"catalog=pystac_client.Client.open(stac_root)search=catalog.search(collections=['mrdem-30'],intersects=lonlat,)# Get the link to the data asset for mrdem-30 dtm and dsmlinks={}forpageinsearch.pages():foriteminpage:links['dtm']=item.assets['dtm'].hreflinks['dsm']=item.assets['dsm'].href# Read value from coordinatesforasset,hrefinlinks.items():withrasterio.open(href)assrc:forvalinsrc.sample([(x1,y1)]):print(f'{asset} : {val}')