import hvplot.xarray
import s3fs
import xarray as xr
import zarr
from pyproj import Transformer
# Open the Zarr store
fs = s3fs.S3FileSystem(profile="default", asynchronous=True)
zstore = zarr.storage.FsspecStore(fs, path=store[5:])
ds = xr.open_zarr(zstore)
# Create a transformer to convert from lat/lon to the mosaic CRS (UTM 18N)
transformer = Transformer.from_crs("EPSG:4326", "EPSG:32618", always_xy=True)
# Define a small preview area (~2km x 2km) near the center of the AOI
# Using the full AOI at 1m resolution would be too large to render efficiently
preview_center_lon = (minx + maxx) / 2
preview_center_lat = (miny + maxy) / 2
preview_size = 0.01 # ~1km in each direction (total ~2km x 2km)
preview_min_lon = preview_center_lon - preview_size
preview_max_lon = preview_center_lon + preview_size
preview_min_lat = preview_center_lat - preview_size
preview_max_lat = preview_center_lat + preview_size
# Transform preview bounding box coordinates from lat/lon to UTM meters
(min_x, max_x), (min_y, max_y) = transformer.transform(
[preview_min_lon, preview_max_lon],
[preview_min_lat, preview_max_lat]
)
# Slice the dataset to the preview bounding box
# y=slice(max_y, min_y) handles the standard "North-to-South" image orientation
ds_subset = ds.sel(
x=slice(min_x, max_x),
y=slice(max_y, min_y)
)
# Select RGB bands and create array for visualization
# NAIP bands are named: r, g, b, ir
rgb = ds_subset.sel(band=["r", "g", "b"])["variables"]
# Handle time dimension if present
if "time" in rgb.dims:
rgb = rgb.isel(time=0)
# Normalize values for display (NAIP values typically 0-255)
rgb_normalized = rgb / 255.0
rgb_normalized = rgb_normalized.clip(0, 1)
# Visualize as RGB composite
rgb_normalized.hvplot.rgb(
x="x",
y="y",
bands="band",
data_aspect=1,
xaxis=False,
yaxis=False,
title="NAIP Mosaic (RGB) - Preview",
frame_width=600,
)