import argparse
import json
import geopandas as gpd
import numpy as np
import rasterio
from rasterio.mask import mask
from rasterio.session import AWSSession
from rasterio.warp import reproject
from shapely.geometry import box
Resampling with rasterio (S3 storage, NetCDF File, NetCDF4 driver, VSIS3 virtualization, earthaccess auth)
def configure_auth(daac):
"""Authenticate using earthaccess"""
import boto3
import earthaccess
= earthaccess.login()
auth = auth.get_s3_credentials(daac)
s3_credentials = boto3.Session(
session =s3_credentials["accessKeyId"],
aws_access_key_id=s3_credentials["secretAccessKey"],
aws_secret_access_key=s3_credentials["sessionToken"],
aws_session_token="us-west-2",
region_name
)= rasterio.Env(
rio_env
AWSSession(session),
)__enter__()
rio_env.return rio_env
def warp_resample(dataset, zoom=0):
from common import earthaccess_args, target_extent
= target_extent[zoom]
te
# Define filepath, driver, and variable information
= earthaccess_args[dataset]
args = f'NETCDF:/vsis3/{args["bucket"]}/{args["folder"]}/{args["filename"]}:{args["variable"]}'
src # Authenticate with earthaccess
with configure_auth(args["daac"]):
# Define source and target projection
= "EPSG:3857"
dstSRS = "EPSG:4326"
srcSRS = height = 256
width with rasterio.open(src) as da:
# Clip dataset to bounds of Web Mercator tile
= box(*te)
bbox = gpd.GeoDataFrame(
geo "geometry": bbox}, index=[0], crs=int(dstSRS.split(":")[1])
{
)= geo.to_crs(crs=srcSRS)
geo = [json.loads(geo.to_json())["features"][0]["geometry"]]
coords = mask(da, shapes=coords, crop=True)
arr, src_transform # Mask and fill array
= arr.astype("float32", casting="unsafe")
ma 0], out=ma, casting="unsafe")
np.multiply(ma, da.scales[0], out=ma, casting="unsafe")
np.add(ma, da.offsets[# Define affine transformation from input to output dataset
= rasterio.transform.from_bounds(*te, width, height)
dst_transform # Create array to host results
= np.zeros((height, width), np.float32)
destination # Reproject dataset
= reproject(
_, transform
ma.squeeze(),
destination,=srcSRS,
src_crs=src_transform,
src_transform=dstSRS,
dst_crs=dst_transform,
dst_transform
)return destination
if __name__ == "__main__":
if "get_ipython" in dir():
# Just call warp_resample if running as a Jupyter Notebook
= warp_resample("mursst")
da else:
# Configure dataset via argpase if running via CLI
= argparse.ArgumentParser(description="Set environment for the script.")
parser
parser.add_argument("--dataset",
="mursst",
defaulthelp="Dataset to resample.",
=["mursst"],
choices
)
parser.add_argument("--zoom",
=0,
defaulthelp="Zoom level for tile extent.",
)= parser.parse_args()
user_args = warp_resample(user_args.dataset, int(user_args.zoom)) da