Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polygon slicing + Notebook download #9

Open
wants to merge 5 commits into
base: subsidence_etienne
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 224 additions & 0 deletions app/assets/sliced_dataset_workbench.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Global Coastal Atlas workbench\n",
"\n",
"In this notebook, we will show how to use the Global Coastal Atlas workbench to access and process data from the Global Coastal Atlas.\n",
"Some functions have been prepared to quickly get data from the area of interest marked on the website."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install requirements\n",
"First, we need to install the requirements. This can take a few minutes."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install shapely xarray rioxarray"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define input\n",
"\n",
"geojson_str = \"\"\"__POLYGON__\"\"\"\n",
"\n",
"zarr_url = \"__ZARR__\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define functions\n",
"A class is defined that can be used for fetching and slicing a remote zarr."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from enum import Enum\n",
"import shapely\n",
"import xarray as xr\n",
"import numpy as np\n",
"\n",
"class DatasetType(Enum):\n",
" RASTER = \"raster\"\n",
" POINT = \"point\"\n",
" \n",
"\n",
"class ZarrSlicer:\n",
"\n",
" @staticmethod\n",
" def get_sliced_dataset(geojson_str: str, zarr_uri: str) -> xr.Dataset:\n",
" \"\"\"Fetch Zarr from remote store and slice with geojson polygon\n",
"\n",
" Args:\n",
" geojson_str (str): String containing geojson polygon\n",
" zarr_uri (str): String containing zarr uri\n",
"\n",
" Returns:\n",
" xr.Dataset: sliced lazy loaded zarr dataset\n",
" \"\"\"\n",
" polygon_shape = ZarrSlicer._create_shape_from_geojson(geojson_str)\n",
" zarr = ZarrSlicer._get_dataset_from_zarr_url(zarr_uri)\n",
" sliced_zarr = ZarrSlicer.slice_xarr_with_polygon(zarr, polygon_shape)\n",
" return sliced_zarr\n",
"\n",
" @staticmethod\n",
" def slice_xarr_with_polygon(\n",
" xarr: xr.Dataset, polygon: shapely.Polygon\n",
" ) -> xr.Dataset:\n",
" \"\"\"Slice xarray dataset with geojson polygon\n",
"\n",
" Args:\n",
" xarr (xr.Dataset): xarray dataset\n",
" polygon (Polygon): geojson polygon\n",
"\n",
" Returns:\n",
" xr.Dataset: sliced xarray dataset\n",
" \"\"\"\n",
" dataset_type = ZarrSlicer._get_dataset_type(xarr)\n",
"\n",
" if dataset_type == DatasetType.RASTER:\n",
" spatial_dims = ZarrSlicer._get_spatial_dimensions(xarr)\n",
" indexer = ZarrSlicer._get_indexer_from_raster(xarr, polygon, spatial_dims)\n",
" elif dataset_type == DatasetType.POINT:\n",
" points = ZarrSlicer._create_points_from_xarr(xarr)\n",
" boolean_mask = ZarrSlicer._get_boolean_mask_from_points(points, polygon)\n",
" spatial_dims = ZarrSlicer._get_spatial_dimensions(xarr)\n",
"\n",
" indexer = {spatial_dims[0]: boolean_mask}\n",
" else:\n",
" raise ValueError(\"Dataset type not supported\") \n",
" \n",
" sliced_xarr = xarr.sel(indexer)\n",
" return sliced_xarr\n",
"\n",
" @staticmethod\n",
" def _get_dataset_type(xarr: xr.Dataset) -> str:\n",
" \"\"\"Get dataset type from xarray dataset. We differentiate between\n",
" raster and point datasets\"\"\"\n",
" # if lat and lon are dimensions, we assume it is a raster dataset\n",
" if \"lat\" in xarr.dims and \"lon\" in xarr.dims:\n",
" return DatasetType.RASTER\n",
" else:\n",
" return DatasetType.POINT\n",
"\n",
" @staticmethod\n",
" def _create_points_from_xarr(xarr: xr.Dataset) -> shapely.MultiPoint:\n",
" \"\"\"Create shapely multipoint from xarray dataset\"\"\"\n",
" lats = xarr.coords[\"lat\"].values\n",
" lons = xarr.coords[\"lon\"].values\n",
" points = shapely.points(lons, lats)\n",
" return points\n",
"\n",
" @staticmethod\n",
" def _get_spatial_dimensions(xarr: xr.Dataset) -> list[str]:\n",
" \"\"\"Get spatial dimension from xarray dataset\"\"\"\n",
" dims = {xarr.lat.dims[0], xarr.lon.dims[0]}\n",
" return list(dims)\n",
"\n",
" @staticmethod\n",
" def _get_boolean_mask_from_points(\n",
" points: shapely.MultiPoint, polygon: shapely.Polygon\n",
" ) -> [bool]:\n",
" \"\"\"Get boolean mask from points and polygon\"\"\"\n",
" return shapely.within(points, polygon)\n",
"\n",
" @staticmethod\n",
" def _get_indexer_from_raster(\n",
" raster: xr.Dataset, polygon: shapely.Polygon,\n",
" spatial_dims: list[str]\n",
" ) -> [bool]:\n",
" \"\"\"Get boolean mask from raster and polygon\"\"\"\n",
" spatial_dim_size = { dim: len(raster[dim].values) for dim in spatial_dims }\n",
"\n",
" coords = np.stack(np.meshgrid(\n",
" raster[spatial_dims[1]].values, raster[spatial_dims[0]].values\n",
" ),\n",
" -1).reshape(\n",
" spatial_dim_size[spatial_dims[0]], \n",
" spatial_dim_size[spatial_dims[1]], 2)\n",
"\n",
" raster_points = shapely.points(coords)\n",
"\n",
" mask = shapely.within(raster_points, polygon_shape)\n",
"\n",
" # Reduce mask to square shape\n",
" # TODO: create point wise indexing for DataSet; \n",
" indexer = {\n",
" 'lat': mask.any(axis=1),\n",
" 'lon': mask.any(axis=0)\n",
" }\n",
" return indexer\n",
" \n",
" @staticmethod\n",
" def _create_shape_from_geojson(geojson: str) -> shapely.Polygon:\n",
" \"\"\"Create shapely polygon from geojson polygon\"\"\"\n",
" return shapely.from_geojson(geojson)\n",
"\n",
" @staticmethod\n",
" def _get_dataset_from_zarr_url(url: str) -> xr.Dataset:\n",
" \"\"\"Get zarr store from url\"\"\"\n",
" return xr.open_zarr(url)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fetch the sliced data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"sliced_xarr = ZarrSlicer.get_sliced_dataset(geojson_str, zarr_uri=zarr_url)\n",
"sliced_xarr"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
File renamed without changes.
3 changes: 3 additions & 0 deletions app/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export default defineNuxtConfig({
noExternal: ['vuetify'],
},
},
build: {
transpile: [/echarts/, /zrender/, /tslib/, /resize-detector/],
},
serverHandlers:
process.env.NODE_ENV === 'development'
? [
Expand Down
Loading