diff --git a/.gitignore b/.gitignore
index 39300a4..7f59689 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
python/wherobots-ai/gpu/.ipynb_checkpoints/
python/wherobots-ai/.ipynb_checkpoints/
python/wherobots-ai/conf/.ipynb_checkpoints/
+_deprecated
.DS_Store
diff --git a/FirstWherobotsNotebook.ipynb b/FirstWherobotsNotebook.ipynb
deleted file mode 100644
index f3515c3..0000000
--- a/FirstWherobotsNotebook.ipynb
+++ /dev/null
@@ -1,322 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "9b94b2f1-7f05-4ceb-86b9-50755df240a6",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Your First Wherobots Cloud Notebook\n",
- "\n",
- "Welcome to Wherobots Cloud! This notebook will introduce some basic concepts of working with spatial data in WherobotsDB including:\n",
- "\n",
- "* Introducing the Wherobots Open Data Catalog\n",
- "* Querying data with Spatial SQL\n",
- "* Creating geospatial visualizations in the Wherobots Cloud notebook environment\n",
- "\n",
- "Along the way we'll introduce some important concepts for working with WherobotsDB like the Spatial DataFrame data structure and querying WherobotsDB databases and tables using Spatial SQL.\n",
- "\n",
- "Let's get started!"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e46ec2af-33de-42ca-aec0-2ab0e19e40cc",
- "metadata": {},
- "source": [
- "This video provides a short overview of the Wherobots Cloud platform"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c960808f-d52b-4754-93a0-c54fb7fbbb5f",
- "metadata": {},
- "outputs": [],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo('ErkhBuUz-LM', width=560, height=315)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "18b9f4de-a28c-49e3-b0be-f255790516fa",
- "metadata": {},
- "source": [
- "# The Wherobots Notebook Experience\n",
- "\n",
- "The Wherobots notebook experience is the main developer interface for working with WherobotsDB. This Jupyter environment allows for running existing notebooks in Python or Scala, creating new notebooks, and loading external notebooks including via git version control. You can run each cell individually or select Run >> Run All Cells from the menu to execute the entire notebook."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "24c235de-96e5-46c2-a227-d79140858501",
- "metadata": {},
- "source": [
- "# Configuring Sedona and Spark\n",
- "\n",
- "WherobotsDB is a distributed geospatial analytics database engine powered by Apache Sedona and that runs on top of Apache Spark. Wherobots Cloud takes care of managing the Spark cluster so you don't need to think about Spark and can instead focus on your data analysis.\n",
- "\n",
- "To get started with WherobotsDB we first need to create a `SedonaContext` object. The `SedonaContext` can contain optional configuration for defining what cloud object stores or other data sources our environment is able to access. Your organization's catalogs and the [Wherobots Open Data catalogs](https://docs.wherobots.com/latest/tutorials/opendata/introduction/) are always automatically configured so they're readily available in your notebooks and jobs."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8ff66e4b-cbf9-4a0f-9fc1-7872984d8f19",
- "metadata": {},
- "outputs": [],
- "source": [
- "from sedona.spark import *\n",
- "\n",
- "config = SedonaContext.builder().getOrCreate()\n",
- "sedona = SedonaContext.create(config)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "87c4acf2-2c74-49eb-a47f-e8db4a3365ce",
- "metadata": {},
- "source": [
- "# Working With Data - The Wherobots Open Data Catalog\n",
- "\n",
- "Wherobots Cloud includes access to the [Wherobots Open Data Catalog](https://docs.wherobots.com/latest/tutorials/opendata/introduction/), a collection of open datasets that have been curated and transformed into the [Havasu spatial table format](https://docs.wherobots.com/latest/references/havasu/introduction/) for fast efficient geospatial processing.\n",
- "\n",
- "Community (free tier) users have access to data from the Overture Maps dataset through the `wherobots_open_data` catalog. Upgrading to the Professional Edition includes access to the `wherobots_pro_data` catalog with many additional datasets including weather, wildfire, and surface temperature, US Census, transportation data, and more.\n",
- "\n",
- "To access the open data tables we can first list all databases in the `wherobots_open_data` catalog:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8a0d787c-7bf3-4825-8ed9-5e5423d88a22",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SHOW SCHEMAS IN wherobots_open_data\").show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e9b087a7-a432-464d-b182-c79c55e15b5b",
- "metadata": {},
- "source": [
- "Next, we can view each table available in the `overture` database:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a7ec80f9-105b-4e20-a5d1-8d0456a8d83a",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SHOW tables IN wherobots_open_data.overture\").show(truncate=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3859dc3d-7ae8-45f4-8a2f-60dcb0382ff2",
- "metadata": {},
- "source": [
- "Each table has a rich schema as described in the [Overture Maps documentation](https://docs.overturemaps.org/). Here we view the schema of the `places_place` table:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "94d47328-d30c-4cec-8b6a-4297248479b4",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.table(\"wherobots_open_data.overture.places_place\").printSchema()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c3030634-8cf5-4244-a45b-a9565b60df69",
- "metadata": {},
- "source": [
- "# Spatial SQL\n",
- "\n",
- "We can use Spatial SQL to query data with WherobotsDB. Spatial SQL extends SQL by adding many functions for working with spatial data. These SQL functions begin with either `ST_` for working with vector data or `RS_` for working with raster data. You can find more information about these spatial SQL functions in the [reference documentation.](https://docs.wherobots.com/latest/references/wherobotsdb/vector-data/Overview/)\n",
- "\n",
- "Let's look at some examples using Spatial SQL to query the Overture data, using the following Spatial SQL functions:\n",
- "\n",
- "* [`ST_GeomFromWKT`](https://docs.wherobots.com/latest/references/wherobotsdb/vector-data/Constructor/?h=st_geomfromwkt#st_geomfromwkt) - create a geometry from Well Known Text (WKT) format \n",
- "* [`ST_DistanceSphere`](https://docs.wherobots.com/latest/references/wherobotsdb/vector-data/Function/?h=st_distancesph#st_distancesphere) - compute the distance between two geometries\n",
- "\n",
- "Along the way we'll work with different geometry types including points, lines, and polygons.\n",
- "\n",
- "First we'll create a view called `places` which will essentially create an alias for our `wherobots_open_data.overture.places_place` table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cc536d5e-4cb4-497f-aef0-c4140bf8945f",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.table(\"wherobots_open_data.overture.places_place\").createOrReplaceTempView(\"places\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e0624c8a-f537-4dbf-bb2d-562b91b1c304",
- "metadata": {},
- "source": [
- "Let's start with a simple query to retrieve some example points of interest, including their name, category, and geometry (in this case a point location):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4225e715-5d85-441e-a334-329866762cd0",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT categories.main AS category, names.common[0].value AS name, geometry FROM places LIMIT 10\").show(truncate=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "71e0dba7-aa22-4971-94b4-2023dfb90028",
- "metadata": {},
- "source": [
- "Let's imagine we're in San Francisco and we want to find all hiking trails nearby. First, we'll use the `ST_GeomFromWKT` SQL function to create a point geometry that represents our current location in San Francisco from longitude, latitude coordinates that we looked up using a GPS device (-122.46552, 37.77196). Then we'll use the `ST_DistanceSphere` function to find all points of interest within a given distance."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "3ebf9b69-4547-4305-8565-98d28c0ba5fb",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"\"\"\n",
- "SELECT names.common[0].value AS name, categories.main AS category, geometry\n",
- "FROM places\n",
- "WHERE ST_DistanceSphere(ST_GeomFromWKT('POINT (-122.46552 37.77196)'), geometry) < 10000\n",
- "AND categories.main = 'hiking_trail'\n",
- "LIMIT 10\n",
- "\"\"\").show(truncate=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "37b58702-1c8c-41c9-a979-f4815192e0a8",
- "metadata": {},
- "source": [
- "So far we've just been printing the results of our queries, but we can also save the results to a variable that represents a spatial DataFrame:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "518f56ba-d419-4d82-aebe-8dd588a1da90",
- "metadata": {},
- "outputs": [],
- "source": [
- "trails_df = sedona.sql(\"\"\"\n",
- "SELECT names.common[0].value AS name, categories.main AS category, geometry\n",
- "FROM places\n",
- "WHERE ST_DistanceSphere(ST_GeomFromWKT('POINT (-122.46552 37.77196)'), geometry) < 10000\n",
- "AND categories.main = 'hiking_trail'\n",
- "\"\"\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "35bcbca0-3ca6-4a53-8cff-8112b7625e15",
- "metadata": {},
- "source": [
- "# Visualizing Data\n",
- "\n",
- "There are many options for visualizing geospatial data in Wherobots notebooks, including:\n",
- "\n",
- "* [SedonaKepler](https://docs.wherobots.com/latest/tutorials/wherobotsdb/vector-data/vector-visualize/?h=sedonakepler#sedonakepler) - an integration with Kepler.gl that allows for visualizing Sedona DataFrames, exploring interactively and configuring styling\n",
- "* [SedonaPyDeck](https://docs.wherobots.com/latest/tutorials/wherobotsdb/vector-data/vector-visualize/?h=sedonakepler#sedonapydeck) - an integration with Deck.gl that allows for creating geometry visualizations, choropleths, scatterplots, and heatmaps\n",
- "* Other Python packages can be installed in the notebook environment, allowing you to leverage any tools from the PyData ecosystem\n",
- "\n",
- "\n",
- "Here we visualize our hiking trails using `SedonaKepler`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "118ab695-3962-4555-ac4e-65f6da53ddc9",
- "metadata": {},
- "outputs": [],
- "source": [
- "SedonaKepler.create_map(trails_df, \"Hiking Trails\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0710f743-a12f-4d21-a2db-1dc0320af193",
- "metadata": {},
- "source": [
- "# Resources\n",
- "\n",
- "Where to go from here? The following resources will help you as you continue your spatial analytics journey with WherobotsDB and Wherobots Cloud:\n",
- "\n",
- "## Example Notebooks\n",
- "\n",
- "* You can find many more example notebooks available in this Jupyter environment in the `notebook_example` directory via the file explorer in the left tab. Specifically:\n",
- " * The `wherobots-db` directory includes further examples for working with WherobotsDB with Python, Spatial SQL and the Overture Maps dataset\n",
- " - [wherobots-db-example-python.ipynb](./python/wherobots-db/wherobots-db-example-python.ipynb) - loading data from Shapefiles, performing spatial joins, and writing as GeoParquet\n",
- " - [wherobots-db-overture-maps.ipynb](./python/wherobots-db/wherobots-db-overture-maps.ipynb) - explore the Overture Maps dataset including points of interest, administrative boundaries, and road networks \n",
- " - [tile-generation-example.ipynb](./python/wherobots-db/tile-generation-example.ipynb) - generate PMTiles vector map tiles for rendering maps using WherobotsDB's scalable vector tiles generator\n",
- " * The `havasu` directory contains examples on working with the Havasu spatial table to perform ETL and data analysis using vector and raster data\n",
- " - [havasu-iceberg-geometry-etl.ipynb](./python/havasu/havasu-iceberg-geometry-etl.ipynb) - creating Havasu tables, performing spatial opertions, working with spatial indexes to optimize performance\n",
- " - [havasu-iceberg-raster-etl.ipynb](./python/havasu/havasu-iceberg-raster-etl.ipynb) - working with the EuroSAT raster dataset as Havasu tables, raster opertions, handling CRS transforms, and benchmarking raster geometry operations\n",
- " - [havasu-iceberg-outdb-raster-etl.ipynb](./python/havasu/havasu-iceberg-outdb-raster-etl.ipynb) - demonstrates the out-db method of working with large rasters in WherobotsDB, loading a large GeoTiff and splitting into tiles, joining vector data with rasters\n",
- " * The notebooks in the `wherobots-ai` directory show how to make use of WherobotsAI features like raster inference and map matching\n",
- " - [gpu/segmentation.ipynb](./python/wherobots-ai/gpu/segmentation.ipynb) - demonstrates Wherobots Query Inference to identify solar farms from satellite imagery\n",
- " - [gpu/classification.ipynb](./python/wherobots-ai/gpu/classification.ipynb) - demonstrates Wherobots Query Inference to identify offshore wind farms from satellite imagery\n",
- " - [gpu/object_detection.ipynb](./python/wherobots-ai/gpu/object_detection.ipynb) - demonstrates Wherobots Query Inference to classify land cover from satellite imagery\n",
- " - [mapmatching_example.ipynb](./python/wherobots-ai/mapmatching_example.ipynb) - matching noisy GPS trajectory data to OpenStreetMap road segments and visualizing the results\n",
- "\n",
- "*Note: Only 1 notebook can be run at a time. If you want to run another notebook, please shut down the kernel of the current notebook first (See instructions [here](https://jupyterlab.readthedocs.io/en/stable/user/running.html)).*\n",
- "\n",
- "## Online Resources\n",
- "\n",
- "* [Wherobots Online Community](https://community.wherobots.com/) - Ask questions, share your projects, explore what others are working on in the community, and connect with other members of the community\n",
- "* [Wherobots YouTube Channel](https://www.youtube.com/@wherobotsinc.5352) - Find technical tutorials, example videos, and presentations from spatial data experts on the Wherebots YouTube Channel\n",
- "* [Wherobots Documentation](https://docs.wherobots.com/) - The documentation includes information about how to manage your Wherobots Cloud account, how to work with data using WherobotsDB, as well as reference documentation\n",
- "* [Wherobots Blog](https://wherobots.com/blogs/) - Keep up to date with the Wherobots and Apache Sedona community including new product announcements, technical tutorials, and highlighting spatial analytics projects"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "74f138e8",
- "metadata": {},
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.11"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/README.md b/README.md
index c530e91..7b40a29 100644
--- a/README.md
+++ b/README.md
@@ -15,14 +15,16 @@ or your direct support channel if you are a Professional or Enterprise Edition c
```
.
-├── python # Python examples
-│ ├──havasu # Havasu and data processing examples
-│ ├──wherobots-ai # Wherobots AI examples
-│ │ └──gpu # GPU-accelerated, Raster Inference examples
-│ └──wherobots-db # WherobotsDB examples
-├── scala # Scala examples
-│ ├──sedona-maven-example # A template for packaging jars
-│ └──wherobots-db # WherobotsDB examples
-│── FirstWherobotsNotebook.ipynb # Welcome notebook for first-time users
-└── README.md
+├── README.md
+├── advanced
+├── datasets
+│ └── foursquare-places-example
+│ └── assets
+├── get-started
+│ └── map-config
+├── snippets
+├── wherobots-ai
+│ ├── conf
+│ ├── gpu
+│ │ ├── img
```
diff --git a/python/wherobots-db/tile-generation-example.ipynb b/advanced/tile-generation-example.ipynb
similarity index 100%
rename from python/wherobots-db/tile-generation-example.ipynb
rename to advanced/tile-generation-example.ipynb
diff --git a/python/wherobots-db/wherobots-db-example-python.ipynb b/advanced/wherobots-db-example-python.ipynb
similarity index 100%
rename from python/wherobots-db/wherobots-db-example-python.ipynb
rename to advanced/wherobots-db-example-python.ipynb
diff --git a/python/wherobots-db/wherobots-db-knn-joins.ipynb b/advanced/wherobots-db-knn-joins.ipynb
similarity index 100%
rename from python/wherobots-db/wherobots-db-knn-joins.ipynb
rename to advanced/wherobots-db-knn-joins.ipynb
diff --git a/python/wherobots-db/wherobots-db-overture-maps.ipynb b/advanced/wherobots-db-overture-maps.ipynb
similarity index 100%
rename from python/wherobots-db/wherobots-db-overture-maps.ipynb
rename to advanced/wherobots-db-overture-maps.ipynb
diff --git a/python/wherobots-db/wherobots-db-stac-reader.ipynb b/advanced/wherobots-db-stac-reader.ipynb
similarity index 100%
rename from python/wherobots-db/wherobots-db-stac-reader.ipynb
rename to advanced/wherobots-db-stac-reader.ipynb
diff --git a/python/Data/ESA_WorldCover.ipynb b/datasets/ESA_WorldCover.ipynb
similarity index 100%
rename from python/Data/ESA_WorldCover.ipynb
rename to datasets/ESA_WorldCover.ipynb
diff --git a/python/wherobots-db/foursquare-places-example/Foursquare-places-in-Wherobots.ipynb b/datasets/Foursquare-Places-in-Wherobots.ipynb
similarity index 100%
rename from python/wherobots-db/foursquare-places-example/Foursquare-places-in-Wherobots.ipynb
rename to datasets/Foursquare-Places-in-Wherobots.ipynb
diff --git a/python/wherobots-db/foursquare-places-example/assets/choropleth.png b/datasets/foursquare-places-example/assets/choropleth.png
similarity index 100%
rename from python/wherobots-db/foursquare-places-example/assets/choropleth.png
rename to datasets/foursquare-places-example/assets/choropleth.png
diff --git a/python/wherobots-db/foursquare-places-example/assets/map_config.json b/datasets/foursquare-places-example/assets/map_config.json
similarity index 100%
rename from python/wherobots-db/foursquare-places-example/assets/map_config.json
rename to datasets/foursquare-places-example/assets/map_config.json
diff --git a/python/wherobots-db/foursquare-places-example/assets/placemaker_tools_2.png b/datasets/foursquare-places-example/assets/placemaker_tools_2.png
similarity index 100%
rename from python/wherobots-db/foursquare-places-example/assets/placemaker_tools_2.png
rename to datasets/foursquare-places-example/assets/placemaker_tools_2.png
diff --git a/python/wherobots-db/foursquare-places-example/assets/wherobots-1.png b/datasets/foursquare-places-example/assets/wherobots-1.png
similarity index 100%
rename from python/wherobots-db/foursquare-places-example/assets/wherobots-1.png
rename to datasets/foursquare-places-example/assets/wherobots-1.png
diff --git a/python/onboarding/Wherobots-Onboarding-Part-1-Loading-Data.ipynb b/get-started/Wherobots-Onboarding-Part-1-Loading-Data.ipynb
similarity index 100%
rename from python/onboarding/Wherobots-Onboarding-Part-1-Loading-Data.ipynb
rename to get-started/Wherobots-Onboarding-Part-1-Loading-Data.ipynb
diff --git a/python/onboarding/Wherobots-Onboarding-Part-2-Loading-Data.ipynb b/get-started/Wherobots-Onboarding-Part-2-Loading-Data.ipynb
similarity index 100%
rename from python/onboarding/Wherobots-Onboarding-Part-2-Loading-Data.ipynb
rename to get-started/Wherobots-Onboarding-Part-2-Loading-Data.ipynb
diff --git a/python/onboarding/Wherobots-Onboarding-Part-3-Accelerating-Geospatial-Datasets.ipynb b/get-started/Wherobots-Onboarding-Part-3-Accelerating-Geospatial-Datasets.ipynb
similarity index 100%
rename from python/onboarding/Wherobots-Onboarding-Part-3-Accelerating-Geospatial-Datasets.ipynb
rename to get-started/Wherobots-Onboarding-Part-3-Accelerating-Geospatial-Datasets.ipynb
diff --git a/get-started/Wherobots-Onboarding-Part-4-Spatial-Joins.ipynb b/get-started/Wherobots-Onboarding-Part-4-Spatial-Joins.ipynb
new file mode 100644
index 0000000..5efd2e3
--- /dev/null
+++ b/get-started/Wherobots-Onboarding-Part-4-Spatial-Joins.ipynb
@@ -0,0 +1,892 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "452eddae-5506-401a-bbb6-a2265ae88a97",
+ "metadata": {},
+ "source": [
+ "# 🚀 Spatial Joins in Wherobots: A Pythonic Notebook "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9c5ea0f4-2b47-480d-b20d-c3796c60d6ea",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-04T18:26:32.724658Z",
+ "iopub.status.busy": "2025-03-04T18:26:32.724437Z",
+ "iopub.status.idle": "2025-03-04T18:26:32.728362Z",
+ "shell.execute_reply": "2025-03-04T18:26:32.727962Z",
+ "shell.execute_reply.started": "2025-03-04T18:26:32.724643Z"
+ }
+ },
+ "source": [
+ "Welcome to this comprehensive notebook on performing spatial joins in Wherobots using a Python-centric approach. \n",
+ "\n",
+ "In this notebook, we will walk through how to use Apache Sedona with the Wherobots platform to perform spatial operations such as standard spatial joins, nearest neighbor joins, and zonal statistics—all using the DataFrame API. \n",
+ "\n",
+ "We’ll also optimize our processing and visualize our results using interactive tools.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37322354-e387-433f-a454-3b592ebdb1f8",
+ "metadata": {},
+ "source": [
+ "## Introduction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a04dcc30-2f8a-44d9-b841-d1397c92d8ed",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-04T18:26:18.107213Z",
+ "iopub.status.busy": "2025-03-04T18:26:18.106982Z",
+ "iopub.status.idle": "2025-03-04T18:26:18.111363Z",
+ "shell.execute_reply": "2025-03-04T18:26:18.110968Z",
+ "shell.execute_reply.started": "2025-03-04T18:26:18.107196Z"
+ }
+ },
+ "source": [
+ "Spatial joins allow us to merge data from different datasets based on the geographic relationship between their features. This notebook covers:\n",
+ "\n",
+ "- **Standard Spatial Joins:** e.g., finding which points lie within a given polygon.\n",
+ "- **Nearest Neighbor Joins:** e.g., identifying the closest administrative centroid for each facility.\n",
+ "- **Zonal Statistics:** e.g., summarizing data (like average measurements) within each geographic zone.\n",
+ "\n",
+ "We'll discuss optimization techniques such as spatial partitioning using geohashes and visualize our results interactively. Let’s dive in! 😊\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "133fa1cf-8adc-40ab-aea0-39850ef2f961",
+ "metadata": {},
+ "source": [
+ "# 🎬 Environment Setup and Data Preparation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b626ed1d-7ad5-49b2-a4cc-02b5b0eff49b",
+ "metadata": {},
+ "source": [
+ "Before running spatial queries, we must set up our environment. This section covers how to initialize Apache Sedona and load our spatial datasets."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "05a3e135-8a11-4cd3-be33-6a1369ec03b5",
+ "metadata": {},
+ "source": [
+ "🏃🏽 Initialize Sedona"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e90be397-97b6-4d2c-8e68-46f5c69cdf3f",
+ "metadata": {},
+ "source": [
+ "\n",
+ "In this section, we create a Spark session and initialize Sedona. This setup enables us to perform distributed spatial operations.\n",
+ "\n",
+ "```python\n",
+ "# Import required libraries\n",
+ "from sedona.spark import SedonaContext\n",
+ "from pyspark.sql import SparkSession\n",
+ "from pyspark.sql.functions import expr\n",
+ "\n",
+ "# Create or get a Spark session\n",
+ "spark = SparkSession.builder \\\n",
+ " .appName(\"SpatialJoinsPythonicNotebook\") \\\n",
+ " .getOrCreate()\n",
+ "\n",
+ "# Initialize the Sedona context which powers spatial processing\n",
+ "sedona = SedonaContext.create(spark)\n",
+ "\n",
+ "# Confirm initialization\n",
+ "print(\"Sedona has been successfully initialized! 🚀\")\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- We first import necessary modules, including SedonaContext and SparkSession.\n",
+ "- A Spark session is created using the builder pattern, which is the entry point for Spark operations.\n",
+ "- We initialize Sedona with `SedonaContext.create(spark)`, which sets up the spatial processing engine.\n",
+ "- Finally, we print a confirmation message to ensure everything is ready."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64ff61e5-e2ed-4754-8047-9073e3d552bb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sedona.spark import SedonaContext\n",
+ "from pyspark.sql.functions import expr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b7a50783-0a1a-41b3-801b-80ac4efd01d0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create or get a Wherobots session\n",
+ "config = SedonaContext.builder().getOrCreate()\n",
+ "\n",
+ "# Initialize the Sedona context which powers spatial processing\n",
+ "sedona = SedonaContext.create(config)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f050d715-9bfc-4045-af91-71833b0db1ca",
+ "metadata": {},
+ "source": [
+ "# 📀 Load Spatial Data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "de243b07-516f-4e6d-bfa3-263785dc11b5",
+ "metadata": {},
+ "source": [
+ "Now, we load two spatial datasets stored in Wherobots Managed Storage:\n",
+ "- **Polygons:** Represent administrative boundaries.\n",
+ "- **Points:** Represent facility locations.\n",
+ "\n",
+ "```python\n",
+ "# Load the polygon dataset (administrative boundaries) using a Spatial SQL Query\n",
+ "# Using sedona.sql, create a dataframe from the query\n",
+ "query = '''\n",
+ "SELECT \n",
+ " * \n",
+ "FROM\n",
+ " wherobots_open_data.overture_2025_01_22_0.divisions_division_area\n",
+ "WHERE\n",
+ " subtype = 'locality'\n",
+ " AND country = 'US'\n",
+ "'''\n",
+ "\n",
+ "polygons_df = sedona.sql(query)\n",
+ "# (Alternatively, load from a file with spark.read.format(\"geoparquet\") if necessary)\n",
+ "\n",
+ "# Load the points dataset (facilities)\n",
+ "points_df = sedona.table(\"wherobots.sample_data.facilities\")\n",
+ "# (Alternatively, load from a file with spark.read.format(\"geoparquet\"))\n",
+ "\n",
+ "# Display a sample of the polygon dataset\n",
+ "print(\"🔹 Sample of the Polygon Dataset (Administrative Boundaries):\")\n",
+ "polygons_df.show(5, truncate=False)\n",
+ "\n",
+ "# Display a sample of the points dataset\n",
+ "print(\"🔹 Sample of the Points Dataset (Facilities):\")\n",
+ "points_df.show(5, truncate=False)\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- We use the `sedona.table` function to load the data directly from the Wherobots catalog.\n",
+ "- Two DataFrames are created: one for polygons and one for points.\n",
+ "- We then display the first five rows of each dataset to verify the contents. This helps ensure our data is loaded correctly and gives a preview of the schema."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2405e557-f963-40bd-adf6-7e91bd7ce47d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "query = '''\n",
+ "SELECT \n",
+ " * \n",
+ "FROM\n",
+ " wherobots_open_data.overture_2025_01_22_0.divisions_division_area\n",
+ "WHERE\n",
+ " subtype = 'locality'\n",
+ " AND country = 'US'\n",
+ "'''"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "90b8c5de-131e-4b6d-9e30-43c98e5b71d1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "polygons_df = sedona.sql(query)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6dad4886-adf9-44c5-9133-e74feaf2d22d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_df = sedona.table(\"wherobots_open_data.foursquare.places\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2dd4c31-d612-4c9d-b3fe-b5f56c7a9d39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Sample of the Polygon Dataset (Administrative Boundaries):\")\n",
+ "polygons_df.show(5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d98ccb2a-191b-45d6-843c-830bdd39b42c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Sample of the Points Dataset (Facilities):\")\n",
+ "points_df.show(5, truncate=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1ce45917-a5cf-40cf-b0aa-243c65034069",
+ "metadata": {},
+ "source": [
+ "# 🤝🏼 Standard Spatial Join (Pythonic Approach)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6c3c634e-7922-4a7f-8b24-0e5fffe1399c",
+ "metadata": {},
+ "source": [
+ "In a standard spatial join, we want to link points (facilities) with the polygons (administrative boundaries) that contain them. We use spatial predicates like `ST_Intersects`.\n",
+ "\n",
+ "```python\n",
+ "# Alias the DataFrames for clarity\n",
+ "facilities = points_df.alias(\"f\")\n",
+ "admin_boundaries = polygons_df.alias(\"poly\")\n",
+ "\n",
+ "# Perform a spatial join:\n",
+ "# Join the facilities and admin_boundaries DataFrames where the facility geometry\n",
+ "# intersects with the polygon geometry using the ST_Intersects predicate.\n",
+ "spatial_join_df = facilities.join(\n",
+ " admin_boundaries,\n",
+ " expr(\"ST_Intersects(poly.geom, f.geom)\")\n",
+ ")\n",
+ "\n",
+ "# Show a few rows of the spatial join result\n",
+ "print(\"🔹 Standard Spatial Join Results (Facilities within Administrative Boundaries):\")\n",
+ "spatial_join_df.show(10, truncate=False)\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- We alias the points and polygons DataFrames as \"f\" and \"poly\" for easier reference.\n",
+ "- The join condition uses the `ST_Intersects` function, which returns `true` if a point lies within (or touches) a polygon.\n",
+ "- The join operation returns combined rows from both DataFrames where the condition is met.\n",
+ "- We display the first 10 rows to inspect the join result.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a03a1e0e-b270-497e-9876-482a0c8e552a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "facilities = points_df.alias(\"f\")\n",
+ "admin_boundaries = polygons_df.alias(\"poly\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b9f217c5-4186-4d24-b0ba-b2918d68be56",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "spatial_join_df = facilities.join(\n",
+ " admin_boundaries,\n",
+ " expr(\"ST_Intersects(poly.geometry, f.geometry)\")\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ae8374cc-6ac0-4490-a521-e9b91b482737",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Standard Spatial Join Results (Facilities within Administrative Boundaries):\")\n",
+ "spatial_join_df.show(1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5ddc705d-3fbe-40e1-b4a2-7d59b7ad021b",
+ "metadata": {},
+ "source": [
+ "# 🔢 Efficiently Counting Points Within Each Polygon"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0cd392cf-f46d-4262-b3d1-0f2318110f9f",
+ "metadata": {},
+ "source": [
+ "In this step, we combine the spatial join and aggregation into one efficient operation. By directly applying the spatial predicate (`ST_Intersects`) during the join and then aggregating (grouping by polygon ID) to count the points, we allow Wherobots to optimize the query. This minimizes data shuffling and processing by filtering data at the source (e.g., using GeoParquet spatial filter pushdown). This method is particularly beneficial when working with large datasets.\n",
+ "\n",
+ "```python\n",
+ "# Efficiently count the number of facilities (points) that fall inside each polygon.\n",
+ "# This approach directly aggregates the data after filtering with the spatial predicate.\n",
+ "points_count_efficient_df = polygons_df.alias(\"poly\") \\\n",
+ " .join(points_df.alias(\"f\"), expr(\"ST_Intersects(poly.geom, f.geom)\")) \\\n",
+ " .groupBy(\"poly.id\") \\\n",
+ " .agg(expr(\"COUNT(*) as point_count\"))\n",
+ "\n",
+ "# Display the aggregated result\n",
+ "print(\"🔹 Efficient Count of Points in Each Polygon:\")\n",
+ "points_count_efficient_df.show(10, truncate=False)\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- **Spatial Predicate Pushdown:** By using `ST_Intersects` directly in the join condition, Wherobots can push the spatial predicate down to the data source level (especially if you're using spatially optimized formats such as GeoParquet). This means only the relevant data (points that are near or within the polygons) is loaded and processed. 🚀 \n",
+ "- **Single-step Aggregation:** We immediately group the joined result by the polygon's identifier (`poly.id`) and use the `COUNT(*)` aggregate function to determine how many points fall within each polygon. This avoids creating an intermediate, full join result before counting, which is both memory and compute efficient. \n",
+ "- **Performance Gains:** Combining filtering and aggregation reduces unnecessary data movement and computation, making the operation much more efficient on large datasets.\n",
+ "\n",
+ "This method is a best practice when dealing with spatial queries in environments like Wherobots that are optimized for spatial predicates. Enjoy the performance improvements and cleaner code! 😊"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b9e923ef-c1a4-4723-b6bb-ed2e73eebe63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_count_efficient_df = polygons_df.alias(\"poly\") \\\n",
+ " .join(points_df.alias(\"f\"), expr(\"ST_Intersects(poly.geometry, f.geometry)\")) \\\n",
+ " .groupBy(\"poly.id\") \\\n",
+ " .agg(expr(\"COUNT(*) as point_count\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6318d418-4c06-49f3-a525-c9abab13c2ce",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Efficient Count of Points in Each Polygon:\")\n",
+ "points_count_efficient_df.show(10)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ea0fb8fa-944a-499c-bc8b-be085da1342f",
+ "metadata": {},
+ "source": [
+ "# 🏘️ Nearest Neighbor Join"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3bb62686-71a5-4367-9c6a-5aa4668e7116",
+ "metadata": {},
+ "source": [
+ "The nearest neighbor join finds, for each facility, the closest centroid of an administrative area. This can be useful for determining the nearest center point or service area.\n",
+ "\n",
+ "```python\n",
+ "# Compute centroids for each polygon to represent the center of each administrative area.\n",
+ "centroids_df = polygons_df.selectExpr(\"id\", \"ST_Centroid(geom) as centroid\")\n",
+ "\n",
+ "# Display a few centroid records\n",
+ "print(\"🔹 Centroids of Administrative Boundaries:\")\n",
+ "centroids_df.show(5, truncate=False)\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- We create a new DataFrame `centroids_df` by selecting the `id` and computing the centroid of each polygon using the `ST_Centroid` function.\n",
+ "- These centroids will later serve as reference points for our nearest neighbor calculation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "baa91705-5f56-4bd9-9050-23ff86081d4d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "centroids_df = polygons_df.selectExpr(\"id\", \"ST_Centroid(geometry) as centroid\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44d31754-18db-46a8-8c0d-fe1c2998f1f1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Centroids of Administrative Boundaries:\")\n",
+ "centroids_df.show(1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ada13f1f-a89e-405a-a2c3-56977720047a",
+ "metadata": {},
+ "source": [
+ "In this approach, we use the ST_AKNN function to directly obtain the k nearest neighbors for each query geometry. The function signature is: \n",
+ "\n",
+ "```\n",
+ "ST_AKNN(query_geom, object_geom, k, include_ties)\n",
+ "```\n",
+ "\n",
+ "In our example, we assume the following: \n",
+ "- **Queries DataFrame:** Our facilities DataFrame (`points_df`) represents the query geometries. \n",
+ "- **Objects DataFrame:** Our centroids DataFrame (`centroids_df`), which was created earlier by computing the centroid of each polygon, represents the object geometries.\n",
+ "\n",
+ "The SQL equivalent of our operation is: \n",
+ "\n",
+ "```\n",
+ "SELECT\n",
+ " QUERIES.ID AS QUERY_ID,\n",
+ " QUERIES.GEOMETRY AS QUERIES_GEOM,\n",
+ " OBJECTS.GEOMETRY AS OBJECTS_GEOM\n",
+ "FROM QUERIES JOIN OBJECTS ON ST_AKNN(QUERIES.GEOMETRY, OBJECTS.GEOMETRY, 4, FALSE)\n",
+ "```\n",
+ "\n",
+ "Below is the Pythonic implementation:\n",
+ "\n",
+ "```python\n",
+ "# Use ST_AKNN to perform an approximate k-nearest neighbor join between the queries and objects.\n",
+ "# In our example, we join the facilities (points_df) with the centroids (centroids_df),\n",
+ "# returning the four nearest centroids for each facility. The \"false\" parameter indicates that ties are not included.\n",
+ "aknn_df = points_df.alias(\"q\").join(\n",
+ " centroids_df.alias(\"o\"),\n",
+ " expr(\"ST_AKNN(q.geom, o.centroid, 4, false)\")\n",
+ ")\n",
+ "\n",
+ "# Select and rename the columns for clarity.\n",
+ "# Here, we select the query's id and geometry as well as the object's geometry.\n",
+ "aknn_result_df = aknn_df.select(\n",
+ " expr(\"q.id as query_id\"),\n",
+ " expr(\"q.geom as query_geom\"),\n",
+ " expr(\"o.centroid as object_geom\")\n",
+ ")\n",
+ "\n",
+ "# Display the result of the nearest neighbor join using ST_AKNN.\n",
+ "print(\"🔹 Nearest Neighbor Join using ST_AKNN:\")\n",
+ "aknn_result_df.show(10, truncate=False)\n",
+ "```\n",
+ "\n",
+ "**Detailed Markdown Explanation:** \n",
+ "- **Purpose:** \n",
+ " This code uses the `ST_AKNN` function to efficiently find the four closest (k = 4) object geometries (in this case, centroids) for each query geometry (facilities). This method is optimized within Wherobots and leverages the spatial predicate pushdown capabilities of the compute engine.\n",
+ " \n",
+ "- **Process:** \n",
+ " 1. **Aliasing:** \n",
+ " We alias `points_df` as `\"q\"` (representing the queries) and `centroids_df` as `\"o\"` (representing the objects) for easier reference. \n",
+ " 2. **Joining with ST_AKNN:** \n",
+ " The join condition `expr(\"ST_AKNN(q.geom, o.centroid, 4, false)\")` applies the ST_AKNN function to determine whether a given object is among the four nearest neighbors of a query geometry. \n",
+ " 3. **Column Selection:** \n",
+ " After joining, we select and rename columns to clearly indicate the query ID, the query geometry, and the object geometry (centroid) for each match. \n",
+ " 4. **Display:** \n",
+ " Finally, we display the top 10 results. This gives you a clear view of which centroids are among the nearest neighbors for each facility.\n",
+ "\n",
+ "- **Efficiency:** \n",
+ " By using `ST_AKNN`, the engine performs an optimized nearest neighbor search without the need for an expensive cross join or manual windowing. This is especially beneficial when working with large datasets where performance is critical.\n",
+ "\n",
+ "This approach provides a clean, efficient, and Pythonic solution for nearest neighbor joins using Wherobots and Apache Sedona. Enjoy the streamlined spatial analysis!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49740576-8005-47e0-86c9-796ef8ab4f7a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "aknn_df = points_df.alias(\"q\").join(\n",
+ " centroids_df.alias(\"o\"),\n",
+ " expr(\"ST_AKNN(q.geometry, o.centroid, 4, false)\")\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6b1a93fd-c68e-4372-9ee6-fbf14fe5f4c3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "aknn_result_df = aknn_df.select(\n",
+ " expr(\"q.fsq_place_id as query_id\"),\n",
+ " expr(\"q.geometry as query_geom\"),\n",
+ " expr(\"o.centroid as object_geom\")\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "39b86cb5-fc43-4f3c-b70e-e146e65550b8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"🔹 Nearest Neighbor Join using ST_AKNN:\")\n",
+ "aknn_result_df.show(10, truncate=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "aec4a1ff-148a-40b7-bf4e-d980f2c0fefd",
+ "metadata": {},
+ "source": [
+ "# 🦾 Advanced Optimization Techniques"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4bbe90ea-f341-4dff-b12e-7c1cba73bc7c",
+ "metadata": {},
+ "source": [
+ "Optimizing spatial operations is critical for performance, especially with large datasets. One common strategy is to repartition the data using a spatial key, such as a geohash. This improves data locality and reduces shuffle during joins.\n",
+ "\n",
+ "## Repartition Data Using Geohash\n",
+ "\n",
+ "```python\n",
+ "# Add a geohash column to the facilities and polygons DataFrames with a precision level of 5.\n",
+ "points_df = points_df.withColumn(\"geohash\", expr(\"ST_GeoHash(geom, 5)\"))\n",
+ "polygons_df = polygons_df.withColumn(\"geohash\", expr(\"ST_GeoHash(geom, 5)\"))\n",
+ "\n",
+ "# Repartition the DataFrames based on the geohash column to group nearby features together.\n",
+ "points_df = points_df.repartition(\"geohash\")\n",
+ "polygons_df = polygons_df.repartition(\"geohash\")\n",
+ "\n",
+ "print(\"🔹 DataFrames repartitioned by geohash for improved spatial join performance!\")\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- The `ST_GeoHash` function converts each geometry into a geohash string. The precision parameter (here, 5) determines the spatial resolution.\n",
+ "- Repartitioning by geohash ensures that spatially proximate features are processed in the same partition, which can significantly speed up join operations."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8f584252-4e2d-4cb0-b038-03a0082dbb57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%time\n",
+ "spatial_join_df.count()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "88ffd712-ddd8-4795-86f0-bcd76849d0c5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_df = points_df.withColumn(\"geohash\", expr(\"ST_GeoHash(geometry, 5)\"))\n",
+ "polygons_df = polygons_df.withColumn(\"geohash\", expr(\"ST_GeoHash(geometry, 5)\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2e325ca7-7ff8-4d28-bacf-fb7dac5d29df",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_df = points_df.repartition(\"geohash\")\n",
+ "polygons_df = polygons_df.repartition(\"geohash\")\n",
+ "print(\"🔹 DataFrames repartitioned by geohash for improved spatial join performance!\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38e2474b-685d-428d-9e7f-a6bb781b4736",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Alias the DataFrames for clarity\n",
+ "facilities = points_df.alias(\"f\")\n",
+ "admin_boundaries = polygons_df.alias(\"poly\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9221ffc5-0e8b-4cdb-b1a3-8fe20ebf4cb5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "spatial_join_df_partition = facilities.join(\n",
+ " admin_boundaries,\n",
+ " expr(\"ST_Intersects(poly.geometry, f.geometry)\")\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dcda8f45-62aa-4097-90b0-9515a0c786e0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%time\n",
+ "spatial_join_df_partition.count()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3467ca88-f2b6-477d-8587-122894ba3c93",
+ "metadata": {},
+ "source": [
+ "# 💅🏼 Visualizing Spatial Join Results with SedonaKepler"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e4ca759b-fcb6-46b4-9a41-00b170fffc9b",
+ "metadata": {},
+ "source": [
+ "Wherobots offers interactive visualization tools to help you explore your spatial data. We will use SedonaKepler and SedonaPyDeck to visualize our spatial join and zonal statistics results.\n",
+ "\n",
+ "### 7.1 Visualizing Spatial Join Results with SedonaKepler\n",
+ "\n",
+ "```python\n",
+ "# Import SedonaKepler for interactive mapping\n",
+ "from sedona.visualize import SedonaKepler\n",
+ "\n",
+ "# Create an interactive map from the spatial join DataFrame.\n",
+ "# The map will show facilities along with the administrative boundaries they fall within.\n",
+ "kepler_map = SedonaKepler.create_map(df=spatial_join_df, name=\"Facilities_Within_Zones\")\n",
+ "\n",
+ "# Display the interactive map in your Jupyter Notebook\n",
+ "kepler_map.show()\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- SedonaKepler integrates with KeplerGl to provide interactive spatial visualizations.\n",
+ "- The `create_map` function takes the spatial join DataFrame and renders an interactive map.\n",
+ "- This is especially useful for exploring the spatial relationships between facilities and boundaries visually.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "042c4e70-1b0b-4a10-aa5f-5d20a4836174",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define the WKT polygon as a string\n",
+ "wkt_polygon = \"POLYGON((-84.656729 33.983118, -84.109483 33.983118, -84.109483 33.562116, -84.656729 33.562116, -84.656729 33.983118))\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d1985a0b-7d24-4661-a5cc-ed739ae9b1d7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "detailed_facilities_df = spatial_join_df.select(\n",
+ " \"f.fsq_place_id\", # Unique facility identifier\n",
+ " \"f.name\", # Facility name\n",
+ " \"f.address\", # Facility address\n",
+ " \"f.locality\", # Locality information\n",
+ " \"f.region\", # Region name\n",
+ " \"f.postcode\", # Postal code\n",
+ " \"f.admin_region\", # Administrative region\n",
+ " \"f.post_town\", # Post town\n",
+ " \"f.country\", # Country name\n",
+ " \"f.geometry\", # Facility geometry\n",
+ " \"poly.names\" # Additional name information\n",
+ ").filter(\n",
+ " expr(f\"ST_Intersects(geometry, ST_GeomFromText('{wkt_polygon}'))\")\n",
+ ").selectExpr(\"*\", \"names.primary\") \\\n",
+ ".drop(\"names\")\n",
+ "\n",
+ "# Display the first few rows of the resulting DataFrame\n",
+ "print(\"🔹 Detailed Facility Information from spatial_join_df:\")\n",
+ "detailed_facilities_df.count()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "743f7520-deb2-46dc-af9e-1302de10638e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sedona.maps.SedonaKepler import SedonaKepler\n",
+ "\n",
+ "# Create an interactive map from the spatial join DataFrame.\n",
+ "# The map will show facilities along with the administrative boundaries they fall within.\n",
+ "kepler_map = SedonaKepler.create_map(df=detailed_facilities_df, name=\"Facilities_Within_Zones\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9b387254-f978-4dfd-a2da-26a462f32753",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "kepler_map"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d182e783-5b15-4304-ac9a-af95e9904496",
+ "metadata": {},
+ "source": [
+ "# 🖥️ Creating a Choropleth Map for Point in Polygon Join with SedonaPyDeck"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "106427c7-e56c-40db-94f8-5f4a102a9076",
+ "metadata": {},
+ "source": [
+ "\n",
+ "```python\n",
+ "# Import SedonaPyDeck for creating choropleth maps\n",
+ "from sedona.maps.SedonaPyDeck import SedonaPyDeck\n",
+ "\n",
+ "# Create a choropleth map using the zonal statistics DataFrame.\n",
+ "# The zones are colored based on the 'avg_measurement' column, highlighting variations across regions.\n",
+ "choropleth_map = SedonaPyDeck.create_choropleth_map(\n",
+ " df=zonal_stats_df,\n",
+ " plot_col=\"avg_measurement\" # This column drives the color intensity\n",
+ ")\n",
+ "\n",
+ "# Display the choropleth map in your Jupyter Notebook\n",
+ "choropleth_map.show()\n",
+ "```\n",
+ "\n",
+ "*Detailed Explanation:* \n",
+ "- SedonaPyDeck leverages the pydeck library to create visually appealing maps.\n",
+ "- By passing the `zonal_stats_df` and specifying the `plot_col`, a choropleth map is created where the color intensity of each zone corresponds to its average measurement.\n",
+ "- This helps to quickly identify areas with high or low average values.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ccd61967-7bf4-45bb-9050-9f46b891d10c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_count_efficient_df = polygons_df.alias(\"poly\") \\\n",
+ " .filter(\n",
+ " expr(f\"ST_Intersects(geometry, ST_GeomFromText('{wkt_polygon}'))\")\n",
+ " ) \\\n",
+ " .join(points_df.alias(\"f\"), expr(\"ST_Intersects(poly.geometry, f.geometry)\")) \\\n",
+ " .groupBy(\"poly.id\", \"poly.geometry\") \\\n",
+ " .agg(expr(\"COUNT(*) as point_count\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "86de5c81-19ad-48c9-946f-181453069962",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "points_count_efficient_df.count()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1c98e468-3b4e-4a19-8491-aba75cdf2dd3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sedona.maps.SedonaPyDeck import SedonaPyDeck\n",
+ "\n",
+ "# Create a choropleth map using the zonal statistics DataFrame.\n",
+ "# The zones are colored based on the 'avg_measurement' column, highlighting variations across regions.\n",
+ "\n",
+ "choropleth_map = SedonaPyDeck.create_choropleth_map(\n",
+ " df=points_count_efficient_df,\n",
+ " plot_col=\"point_count\" # This column drives the color intensity\n",
+ ")\n",
+ "\n",
+ "# Display the choropleth map in your Jupyter Notebook\n",
+ "choropleth_map.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1eff328c-003e-4b67-bddc-652a1dbcb187",
+ "metadata": {},
+ "source": [
+ "# 🎁 Conclusion and Summary"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "407dfba6-8270-422e-bf0e-91802ceed10e",
+ "metadata": {},
+ "source": [
+ "### Summary of Key Steps:\n",
+ "- **Environment Setup:** We initialized Spark and Sedona for spatial processing.\n",
+ "- **Data Loading:** We loaded two spatial datasets—administrative boundaries (polygons) and facilities (points).\n",
+ "- **Standard Spatial Join:** We performed a join using the `ST_Intersects` predicate to link facilities with their containing administrative boundaries.\n",
+ "- **Nearest Neighbor Join:** We computed centroids for administrative areas and then used a cross join with window functions to find the nearest centroid for each facility.\n",
+ "- **Optimization:** We improved join performance by repartitioning data based on geohash values.\n",
+ "- **Visualization:** We created interactive maps using SedonaKepler and SedonaPyDeck to visualize spatial join and zonal statistics results.\n",
+ "\n",
+ "### Final Thoughts:\n",
+ "This notebook provides a detailed, Pythonic approach to handling spatial joins and related spatial operations in Wherobots using Apache Sedona. By leveraging Python’s DataFrame API, we maintain clean and readable code that is easy to modify and extend. Happy spatial data processing! 😊\n",
+ "\n",
+ "For additional details and further learning:\n",
+ "- Check out the [Wherobots Documentation](https://docs.wherobots.com) for advanced topics.\n",
+ "- Visit the [Apache Sedona GitHub Repository](https://github.com/apache/sedona) for source code and examples."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7d0427ac-377a-4c7d-a859-76ea5a5d9160",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.11.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/python/onboarding/map-config/central_park_config.json b/get-started/map-config/central_park_config.json
similarity index 100%
rename from python/onboarding/map-config/central_park_config.json
rename to get-started/map-config/central_park_config.json
diff --git a/python/onboarding/map-config/config.json b/get-started/map-config/config.json
similarity index 100%
rename from python/onboarding/map-config/config.json
rename to get-started/map-config/config.json
diff --git a/python/havasu/havasu-iceberg-geometry-etl.ipynb b/python/havasu/havasu-iceberg-geometry-etl.ipynb
deleted file mode 100644
index 7c878e2..0000000
--- a/python/havasu/havasu-iceberg-geometry-etl.ipynb
+++ /dev/null
@@ -1,516 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "9ea9f554-7ff8-414c-95e5-98fbf9e8b809",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Havasu Geometry ETL Example\n",
- "\n",
- "This notebook demonstrates working with Havasu, a spatial table format, using a taxi pickup dataset. [Read more about Havasu in the Wherobots documentation.](https://docs.wherobots.com/latest/references/havasu/introduction/)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fb738fb5-68c1-4de1-8b85-da815f952e7a",
- "metadata": {},
- "outputs": [],
- "source": [
- "from pyspark.sql import SparkSession\n",
- "from pyspark.sql.functions import expr, col\n",
- "from sedona.spark import *"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a05688e6-cc34-41a4-acfc-3d547bd9bf53",
- "metadata": {},
- "source": [
- "# Define Sedona Context"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "20d8806e-8356-44f0-8981-dae801fb5191",
- "metadata": {},
- "outputs": [],
- "source": [
- "config = SedonaContext.builder().appName('havasu-iceberg-geometry-etl')\\\n",
- " .config(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\")\\\n",
- " .getOrCreate()\n",
- "sedona = SedonaContext.create(config)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "66e3a4f9-8bbb-48ef-a557-3478382f6ea5",
- "metadata": {},
- "source": [
- "# Load Taxi Pickup Records In WherobotsDB"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2ccfff4a-84d3-40e0-86b8-542a0d08301f",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxidf = sedona.read.format('csv').option(\"header\",\"true\").option(\"delimiter\", \",\").load(\"s3://wherobots-examples/data/nyc-taxi-data.csv\")\n",
- "taxidf = taxidf.selectExpr('ST_Point(CAST(Start_Lon AS Decimal(24,20)), CAST(Start_Lat AS Decimal(24,20))) AS pickup', 'Trip_Pickup_DateTime', 'Payment_Type', 'Fare_Amt')\n",
- "taxidf = taxidf.filter(col(\"pickup\").isNotNull())\n",
- "taxidf.show(5)\n",
- "taxidf.createOrReplaceTempView('taxiDf')"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "094dfa53-fa75-472e-8293-230e90284390",
- "metadata": {},
- "source": [
- "# Manage taxi pickup data using Havasu"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1941b835-9001-40df-9959-9b30819b4f2c",
- "metadata": {},
- "source": [
- "Havasu is a data lake for geospatial data. Users can manage their datasets as Havasu tables."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1970abf4-b879-4241-a0b4-5d183e42805e",
- "metadata": {},
- "source": [
- "## Save DataFrame to a Havasu Table"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4857c2a4-10c1-4fae-97ee-30ee7744995c",
- "metadata": {
- "is_executing": true
- },
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE NAMESPACE IF NOT EXISTS wherobots.test_db\")\n",
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.taxi\")\n",
- "taxidf.writeTo(\"wherobots.test_db.taxi\").create()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "daa30e17-c54c-4602-b506-6135db535b04",
- "metadata": {},
- "source": [
- "## Read taxi pickup records from Havasu Table"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f884111a-51a1-4b47-ab7e-1f7daf00051b",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxidf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxidf.show(5)\n",
- "print('total count: ' + str(taxidf.count()))"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "86d6a55c-6395-4fb8-afbc-392538c2d34b",
- "metadata": {},
- "source": [
- "### Note that the pickup column is a geometry column."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a4adb3f9-ba73-4dd7-995e-52423296989e",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxidf.printSchema()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "848462db-59b3-4ca6-b0fe-538b50c1f5fb",
- "metadata": {},
- "source": [
- "### Seamless integration with WherobotsDB functions"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "216369d6-0300-4ed9-a007-d860e8e49128",
- "metadata": {},
- "source": [
- "We can directly apply Sedona ST_ functions to pickup column."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a9a3f3b4-7927-42ca-936c-7c15d598a3dd",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxidf.withColumn(\"buf\", expr(\"ST_Buffer(pickup, 1e-4)\")).show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e3218528-3fe7-4e70-9d6e-d63715971f78",
- "metadata": {},
- "source": [
- "## ACID Properties of Havasu Table"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "eb2014d3-e17f-4126-965a-a1732ef413ef",
- "metadata": {},
- "source": [
- "Havasu supports all ACID properties on a on-disk table, we can append data or modify the table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7ec755e3-ea4f-4bc8-a183-a736539bc9c2",
- "metadata": {},
- "outputs": [],
- "source": [
- "bufdf = taxidf.withColumn(\"pickup\", expr(\"ST_Buffer(pickup, 1e-4)\"))\n",
- "bufdf.writeTo(\"wherobots.test_db.taxi\").append()\n",
- "countAppend = sedona.table(\"wherobots.test_db.taxi\").count()\n",
- "print('total count after append: ' + str(countAppend))"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "489c79d9-dd14-43c2-9a9f-205c58da71ca",
- "metadata": {},
- "source": [
- "We can also use SQL to manipulate data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "51d091a4-dbe6-45e7-b23d-41480a6b4b6b",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi\").show(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4c69a9f5-74af-4d45-9681-1e9f3e69ec71",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"INSERT INTO wherobots.test_db.taxi VALUES (ST_Point(10, 20), '1/26/09 10:20', 'Cash', 3.14)\")\n",
- "sedona.sql(\"INSERT INTO wherobots.test_db.taxi VALUES (ST_Point(10, 20), '1/26/09 10:20', 'Online', 31.4)\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6721ebb3-fd35-41df-8103-0da6e50314bc",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"UPDATE wherobots.test_db.taxi SET Fare_Amt = 314 WHERE ST_Intersects(pickup, ST_Point(10, 20)) AND Payment_Type = 'Online'\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "080ef02f-a648-4d8f-b882-56902ae57f4c",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DELETE FROM wherobots.test_db.taxi WHERE Payment_Type = 'Online'\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c68184a2-a331-4386-9b52-e120f78ff458",
- "metadata": {},
- "source": [
- "## Time Travel"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "691713b1-e4fd-4f94-8a34-f2c5812797de",
- "metadata": {},
- "source": [
- "We can view table history and read a particular version of the table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "301b9120-40b5-4061-a8a5-d4252381fefe",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi.history ORDER BY made_current_at\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7fc75b09-4093-4bdf-b4b6-de6ee3002ffd",
- "metadata": {},
- "outputs": [],
- "source": [
- "snapshots = sedona.sql(\"SELECT * FROM wherobots.test_db.taxi.history ORDER BY made_current_at\").collect()\n",
- "snapshot_1 = snapshots[1]['snapshot_id']"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bda39783-ed36-40f0-aa35-851e90000258",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.table(\"wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0cea85c2-6808-43d2-9a09-e7d95e98d0d6",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.read.option(\"snapshot-id\", snapshot_1).table(\"wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fa1ffe7c-6e87-43cd-97b6-9825a961a5d1",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi VERSION AS OF {}\".format(snapshot_1)).count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "aa98acc0-c465-498c-96b3-46e96639bfce",
- "metadata": {},
- "source": [
- "Now let's roll back to version 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "06711614-ea1f-460f-b7ed-ae24db17a8aa",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"CALL wherobots.system.rollback_to_snapshot('wherobots.test_db.taxi', {})\".format(snapshot_1))\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "6ca47a6e-0a09-47fd-85de-07916f883bb8",
- "metadata": {},
- "source": [
- "## Optimize table for faster range query"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2f19040f-479e-4b88-a6b4-86371dd11c90",
- "metadata": {},
- "source": [
- "We run a small range query on the dataset to see how many records we've scanned"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2fd23bf9-0a84-47a6-8f14-5f05ab5aac7d",
- "metadata": {},
- "outputs": [],
- "source": [
- "predicate = \"ST_Intersects(ST_PolygonFromEnvelope(-73.970730, 40.767844, -73.965615, 40.769217), pickup)\"\n",
- "taxidf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxidf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "cad271ba-50a9-40d6-a6ce-7380a449404c.png": {
- "image/png": "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AgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwII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"
- }
- },
- "cell_type": "markdown",
- "id": "bf1aa69c-9d60-4031-a374-cdd8ac2409fe",
- "metadata": {},
- "source": [
- "We can inspect the metrics data and found that Spark scanned all the data to answer this query\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1a0559c5-76e6-4a48-96f3-e74b753a8615",
- "metadata": {},
- "source": [
- "### CREATE SPATIAL INDEX\n",
- "\n",
- "We can run `CREATE SPATIAL INDEX` on the table to sort the records by spatial proximity. Havasu supports sorting the geometry values by their Hilbert index."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "32aa1e93-c8d4-446d-b8c1-96740352aebf",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE SPATIAL INDEX FOR wherobots.test_db.taxi USING hilbert(pickup, 16) OPTIONS map('target-file-count', '30')\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0e9dfdda-2bcc-4c60-b0fb-3660b12f3425",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxidf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxidf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "262fa7c9-9098-4376-bd1a-191acc686927.png": {
- "image/png": "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"
- }
- },
- "cell_type": "markdown",
- "id": "e9089ff5-3185-436f-b3c8-7f1750fd1f5a",
- "metadata": {},
- "source": [
- "The same query scanned less data, this is because the spatial filter pushdown works better on sorted tables.\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5931f9ab-34ed-4c60-8c6b-8f2673d84c21",
- "metadata": {},
- "source": [
- "### Sorting by geohash value\n",
- "\n",
- "We can sort the pickup column by their geohash values and write them into 30 files."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "08722505-8aee-43ea-b3b2-7fe5568727ca",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.taxi_sorted\")\n",
- "sortedTaxiDf = taxidf.withColumn(\"geohash\", expr(\"ST_GeoHash(ST_Centroid(pickup), 20)\"))\\\n",
- " .sort(col(\"geohash\"))\\\n",
- " .drop(\"geohash\")\n",
- "sortedTaxiDf.write.option(\"target-file-size-bytes\", \"1000000\").format(\"havasu.iceberg\").saveAsTable(\"wherobots.test_db.taxi_sorted\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e9c4db98-16bf-4ebd-9244-5fb8a369efb1",
- "metadata": {},
- "source": [
- "We run the same query on the sorted table, the result is identical with running on the original table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "744b925f-68da-469d-9c3f-f4fdf7e0c8df",
- "metadata": {},
- "outputs": [],
- "source": [
- "sortedTaxiDf = sedona.table(\"wherobots.test_db.taxi_sorted\")\n",
- "sortedTaxiDf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "7972a37f-ae45-45d1-baa6-5c3c282e0a19.png": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAArQAAAIUCAYAAADrIr80AAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAACtKADAAQAAAABAAACFAAAAABu7sNnAABAAElEQVR4AexdB7gUNRe9NBWk9947KAhSFAVFsICgKCogooAgCEoHFVGkWEDpWFAQEKWDCnZEBZHiDwpSBeldeu/8OXkvQ3a2vN19y/Pte+d+3+7MZJJMcpKZObm5uZPishKhEAEiQASIABEgAkSACBCBKEUgZZSWm8UmAkSACBABIkAEiAARIAIaARJadgQiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABEgoWUfIAJEgAgQASJABIgAEYhqBEhoo7r5WHgiQASIABEgAkSACBABElr2ASJABIgAESACRIAIEIGoRoCENqqbj4UnAkSACBABIkAEiAARIKFlHyACRIAIEAEiQASIABGIagRIaKO6+Vh4IkAEiAARIAJEgAgQARJa9gEiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABEgoWUfIAJEgAgQASJABIgAEYhqBEhoo7r5WHgiQASIABEgAkSACBABElr2ASJABIgAESACRIAIEIGoRoCENqqbj4UnAkSACBABIkAEiAARIKFlHyACRIAIEAEiQASIABGIagRIaKO6+Vh4IkAEiAARIAJEgAgQARJa9gEiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABFInRwhOHpeZN5+kd8PiWw6KXLwnMily8kRCdaZCBABIkAEiEDyQiBl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nkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJA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qkmpY9fuRn8kBBBAAAEEEGh4geRf7YbPHzlAAAEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQ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"
- }
- },
- "cell_type": "markdown",
- "id": "8e91f9a4-4d7b-4f5c-9ca1-13e3ab700398",
- "metadata": {},
- "source": [
- "The same query scanned less data, this is because the spatial filter pushdown works better on sorted tables.\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "68c86304-25a8-43d6-a22d-617d3ae195ed",
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.11"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/python/havasu/havasu-iceberg-outdb-raster-etl.ipynb b/python/havasu/havasu-iceberg-outdb-raster-etl.ipynb
deleted file mode 100644
index 7cae4aa..0000000
--- a/python/havasu/havasu-iceberg-outdb-raster-etl.ipynb
+++ /dev/null
@@ -1,853 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "55f5091e-8139-4e93-b19f-0749f0a06f92",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Havasu out-db Raster Example\n",
- "\n",
- "In this notebook, we'll demonstrate how to load a large GeoTIFF file stored on S3 as out-db raster, and split it into smaller tiles.\n",
- "\n",
- "We'll also show how to run RS_Value using a DataFrame of points on a large out-db raster. Read more about [Havasu](https://docs.wherobots.com/latest/references/havasu/introduction/), and [WherobotsDB Raster support](https://docs.wherobots.com/latest/references/havasu/raster/raster-overview/) in the documentation."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ebc2a17b-9878-4928-8b14-f9a26bac0c71",
- "metadata": {},
- "source": [
- "# Define Sedona context"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "4f68934f-079f-4812-a293-a9789b2e092a",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T07:49:04.145894Z",
- "iopub.status.busy": "2025-02-04T07:49:04.145450Z",
- "iopub.status.idle": "2025-02-04T07:49:04.773003Z",
- "shell.execute_reply": "2025-02-04T07:49:04.772429Z",
- "shell.execute_reply.started": "2025-02-04T07:49:04.145869Z"
- }
- },
- "outputs": [],
- "source": [
- "from pyspark.sql import SparkSession\n",
- "from pyspark.sql.functions import expr, col, lit\n",
- "from sedona.spark import *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "3c1955df-5b3f-4c48-842a-644c07ae4ebf",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T07:49:06.146759Z",
- "iopub.status.busy": "2025-02-04T07:49:06.146419Z",
- "iopub.status.idle": "2025-02-04T07:49:35.486514Z",
- "shell.execute_reply": "2025-02-04T07:49:35.485616Z",
- "shell.execute_reply.started": "2025-02-04T07:49:06.146734Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Setting default log level to \"WARN\".\n",
- "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n",
- " \r"
- ]
- }
- ],
- "source": [
- "config = SedonaContext.builder().appName('havasu-iceberg-outdb-raster-etl')\\\n",
- " .config(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\")\\\n",
- " .getOrCreate()\n",
- "sedona = SedonaContext.create(config)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "50968218-9a9d-4844-962e-4fd488abf40f",
- "metadata": {},
- "source": [
- "# Load Raster\n",
- "\n",
- "We'll load the world population data, which contains estimated total number of people per grid-cell. The dataset is available to download in Geotiff format at a resolution of 30 arc (approximately 1km at the equator). The projection is Geographic Coordinate System, WGS84.\n",
- "\n",
- "The original data can be retrieved from [here](https://hub.worldpop.org/geodata/summary?id=24777)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 62,
- "id": "c07afe9c-0b2d-4e74-b0c5-cf2886ab0e83",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:20:52.401307Z",
- "iopub.status.busy": "2025-02-04T08:20:52.400974Z",
- "iopub.status.idle": "2025-02-04T08:20:52.472262Z",
- "shell.execute_reply": "2025-02-04T08:20:52.471542Z",
- "shell.execute_reply.started": "2025-02-04T08:20:52.401282Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+\n",
- "| rast|\n",
- "+--------------------+\n",
- "|LazyLoadOutDbGrid...|\n",
- "+--------------------+\n",
- "\n"
- ]
- }
- ],
- "source": [
- "raster_df = sedona.sql(\"SELECT RS_FromPath('s3://wherobots-examples/data/ppp_2020_1km_Aggregated.tif') as rast\")\n",
- "raster_df.show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "85dce265-a41d-478e-aa73-00004251d7d1",
- "metadata": {},
- "source": [
- "We can save this one large out-db raster as a Havasu table. The table will contain one row representing that large out-db raster."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 63,
- "id": "1c1c1ddc-3996-409a-9893-3869ebebdcb4",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:20:54.374634Z",
- "iopub.status.busy": "2025-02-04T08:20:54.374278Z",
- "iopub.status.idle": "2025-02-04T08:20:55.740672Z",
- "shell.execute_reply": "2025-02-04T08:20:55.740120Z",
- "shell.execute_reply.started": "2025-02-04T08:20:54.374609Z"
- }
- },
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE NAMESPACE IF NOT EXISTS wherobots.test_db\")\n",
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.world_pop\")\n",
- "raster_df.writeTo(\"wherobots.test_db.world_pop\").create()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 64,
- "id": "2181ba8b-54e3-469b-a7cd-12d84b1dd48d",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:20:57.372467Z",
- "iopub.status.busy": "2025-02-04T08:20:57.372139Z",
- "iopub.status.idle": "2025-02-04T08:20:57.932627Z",
- "shell.execute_reply": "2025-02-04T08:20:57.931232Z",
- "shell.execute_reply.started": "2025-02-04T08:20:57.372437Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+-----------------------------------------------------------------------------------------------------------+\n",
- "|meta |\n",
- "+-----------------------------------------------------------------------------------------------------------+\n",
- "|{-180.001249265, 83.99958319871001, 43200, 18720, 0.0083333333, -0.0083333333, 0.0, 0.0, 4326, 1, 256, 256}|\n",
- "+-----------------------------------------------------------------------------------------------------------+\n",
- "\n"
- ]
- }
- ],
- "source": [
- "sedona.sql(\"SELECT RS_Metadata(rast) meta FROM wherobots.test_db.world_pop\").show(5, False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4423a1a3-c705-4761-a7be-fe99acae5bf6",
- "metadata": {},
- "source": [
- "# Split raster into tiles\n",
- "\n",
- "Large rasters may not be suitable for performing raster processing tasks that reads all the pixel data. WherobotsDB provides `RS_TileExplode` function for splitting the large raster into smaller tiles. When the input raster is an out-db raster, the generated tiles are out-db rasters referencing different parts of the out-db raster file. This is a pure geo-referencing metadata operation so this is very fast.\n",
- "\n",
- "The tiles generated by `RS_TileExplode` are within their original partition, so all the tiles are within one partition because the original DataFrame has only one row. This dataframe needs to be repartitioned to distribute the tiles to multiple executors, otherwise future processing on these tiles won't be parallelised."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 70,
- "id": "a7525821-e93f-4abc-b009-6e9c99baffa3",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:26:44.965927Z",
- "iopub.status.busy": "2025-02-04T08:26:44.965601Z",
- "iopub.status.idle": "2025-02-04T08:26:45.512999Z",
- "shell.execute_reply": "2025-02-04T08:26:45.512448Z",
- "shell.execute_reply.started": "2025-02-04T08:26:44.965903Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+---+---+--------------------+\n",
- "| x| y| tile|\n",
- "+---+---+--------------------+\n",
- "|150| 55|OutDbGridCoverage...|\n",
- "|139| 37|OutDbGridCoverage...|\n",
- "|146| 31|OutDbGridCoverage...|\n",
- "| 31| 14|OutDbGridCoverage...|\n",
- "|131| 2|OutDbGridCoverage...|\n",
- "+---+---+--------------------+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- }
- ],
- "source": [
- "tile_df = sedona.sql(\"SELECT RS_TileExplode(rast, 256, 256) AS (x, y, tile) FROM wherobots.test_db.world_pop\").repartition(16)\n",
- "tile_df.show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5b05ae39-c944-4e1e-adf3-613e416881e6",
- "metadata": {},
- "source": [
- "# Load raster as tiles (recommended)\n",
- "\n",
- "WherobotsDB provides `raster` data source for loading raster files and splitting the rasters into tiles using one line of code. The loaded tiles will also be repartitioned to all executors to distribute future raster processing workloads. Read more about [Raster loader](https://docs.wherobots.com/latest/references/wherobotsdb/raster-data/Raster-loader/#loading-raster-using-the-raster-loader) in the documentatin."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 66,
- "id": "6b74bb92-2b4a-43a6-91cf-977557bd29bd",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:26:22.033922Z",
- "iopub.status.busy": "2025-02-04T08:26:22.033599Z",
- "iopub.status.idle": "2025-02-04T08:26:22.757027Z",
- "shell.execute_reply": "2025-02-04T08:26:22.756320Z",
- "shell.execute_reply.started": "2025-02-04T08:26:22.033900Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---+---+\n",
- "| rast| x| y|\n",
- "+--------------------+---+---+\n",
- "|OutDbGridCoverage...| 22| 12|\n",
- "|OutDbGridCoverage...|140| 0|\n",
- "|OutDbGridCoverage...| 52| 62|\n",
- "|OutDbGridCoverage...|129| 37|\n",
- "|OutDbGridCoverage...| 83| 67|\n",
- "+--------------------+---+---+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- }
- ],
- "source": [
- "raster_df_tiled = sedona.read.format(\"raster\").option(\"tileWidth\", \"256\").option(\"tileHeight\", \"256\").load(\"s3://wherobots-examples/data/ppp_2020_1km_Aggregated.tif\")\n",
- "raster_df_tiled.show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c86efd92-c022-4faf-97db-f99ce5a577ec",
- "metadata": {},
- "source": [
- "We'll rename the raster column `rast` as `tile` before saving the DataFrame into Havasu table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 67,
- "id": "66913a1f-5ef2-4af3-b332-3a4628d904d3",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:26:24.967913Z",
- "iopub.status.busy": "2025-02-04T08:26:24.967593Z",
- "iopub.status.idle": "2025-02-04T08:26:24.977755Z",
- "shell.execute_reply": "2025-02-04T08:26:24.977120Z",
- "shell.execute_reply.started": "2025-02-04T08:26:24.967887Z"
- }
- },
- "outputs": [],
- "source": [
- "tile_df = raster_df_tiled.select(col(\"rast\").alias(\"tile\"), \"x\", \"y\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "46883296-30e1-4206-a5b9-bdaced97ec96",
- "metadata": {},
- "source": [
- "## Saving as out-db rasters"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 71,
- "id": "ddaf15ad-1eeb-4692-9393-f55dd1c73ae8",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:26:51.854638Z",
- "iopub.status.busy": "2025-02-04T08:26:51.854301Z",
- "iopub.status.idle": "2025-02-04T08:26:53.848805Z",
- "shell.execute_reply": "2025-02-04T08:26:53.848140Z",
- "shell.execute_reply.started": "2025-02-04T08:26:51.854611Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- }
- ],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.world_pop_tiles\")\n",
- "tile_df.writeTo(\"wherobots.test_db.world_pop_tiles\").create()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 72,
- "id": "8a947c4c-92a0-497e-97c5-e051446f8bb2",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:26:54.954105Z",
- "iopub.status.busy": "2025-02-04T08:26:54.953782Z",
- "iopub.status.idle": "2025-02-04T08:26:55.257164Z",
- "shell.execute_reply": "2025-02-04T08:26:55.256329Z",
- "shell.execute_reply.started": "2025-02-04T08:26:54.954081Z"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "12506"
- ]
- },
- "execution_count": 72,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sedona.table(\"wherobots.test_db.world_pop_tiles\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "19c4ae33-8f38-4dbd-9a0c-040ad3b2e6da",
- "metadata": {},
- "source": [
- "## Saving tiles as in-db rasters\n",
- "\n",
- "WherobotsDB provides an `RS_AsInDb` function for converting out-db raster as in-db raster. It needs to fetch all the band data from the raster file. We manually repartition the out-db tile dataset to run this convertion with high parallelism."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 54,
- "id": "0394bca9-df84-41c2-b840-006f5a2890f2",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:18:27.038386Z",
- "iopub.status.busy": "2025-02-04T08:18:27.038077Z",
- "iopub.status.idle": "2025-02-04T08:18:27.873996Z",
- "shell.execute_reply": "2025-02-04T08:18:27.873178Z",
- "shell.execute_reply.started": "2025-02-04T08:18:27.038362Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---+---+\n",
- "| tile| x| y|\n",
- "+--------------------+---+---+\n",
- "|GridCoverage2D[\"g...| 22| 12|\n",
- "|GridCoverage2D[\"g...|140| 0|\n",
- "|GridCoverage2D[\"g...| 52| 62|\n",
- "|GridCoverage2D[\"g...|129| 37|\n",
- "|GridCoverage2D[\"g...| 83| 67|\n",
- "+--------------------+---+---+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- }
- ],
- "source": [
- "indb_tile_df = tile_df.withColumn(\"tile\", expr(\"RS_AsInDb(tile)\"))\n",
- "indb_tile_df.show(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 55,
- "id": "652379d7-db98-4635-b7aa-f9d51198a8a2",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:18:34.358419Z",
- "iopub.status.busy": "2025-02-04T08:18:34.358046Z",
- "iopub.status.idle": "2025-02-04T08:19:01.201442Z",
- "shell.execute_reply": "2025-02-04T08:19:01.200883Z",
- "shell.execute_reply.started": "2025-02-04T08:18:34.358380Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- }
- ],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.world_pop_indb_tiles\")\n",
- "indb_tile_df.writeTo(\"wherobots.test_db.world_pop_indb_tiles\").create()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "id": "3d9374d8-6c8b-461d-9673-1120fa96f964",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:03.893418Z",
- "iopub.status.busy": "2025-02-04T08:19:03.893092Z",
- "iopub.status.idle": "2025-02-04T08:19:04.428377Z",
- "shell.execute_reply": "2025-02-04T08:19:04.427664Z",
- "shell.execute_reply.started": "2025-02-04T08:19:03.893392Z"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "12506"
- ]
- },
- "execution_count": 56,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sedona.table(\"wherobots.test_db.world_pop_indb_tiles\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f08a8115-acf7-4544-95a8-a52294f301a7",
- "metadata": {},
- "source": [
- "## Visualize the tile boundaries on a map"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 57,
- "id": "7db9a72a-e068-48fc-b88e-6f6e32b8c90a",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:08.619474Z",
- "iopub.status.busy": "2025-02-04T08:19:08.619155Z",
- "iopub.status.idle": "2025-02-04T08:19:15.397455Z",
- "shell.execute_reply": "2025-02-04T08:19:15.396842Z",
- "shell.execute_reply.started": "2025-02-04T08:19:08.619448Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---+---+\n",
- "| tile| x| y|\n",
- "+--------------------+---+---+\n",
- "|GridCoverage2D[\"h...| 11| 6|\n",
- "|GridCoverage2D[\"h...| 18| 37|\n",
- "|GridCoverage2D[\"h...| 98| 58|\n",
- "|GridCoverage2D[\"h...|124| 4|\n",
- "|GridCoverage2D[\"h...|123| 61|\n",
- "|GridCoverage2D[\"h...|139| 29|\n",
- "|GridCoverage2D[\"h...| 34| 64|\n",
- "|GridCoverage2D[\"h...|126| 47|\n",
- "|GridCoverage2D[\"h...| 62| 39|\n",
- "|GridCoverage2D[\"h...|116| 33|\n",
- "|GridCoverage2D[\"h...|127| 32|\n",
- "|GridCoverage2D[\"h...|102| 21|\n",
- "|GridCoverage2D[\"h...|124| 31|\n",
- "|GridCoverage2D[\"h...|122| 13|\n",
- "|GridCoverage2D[\"h...|109| 73|\n",
- "|GridCoverage2D[\"h...| 82| 66|\n",
- "|GridCoverage2D[\"h...| 38| 41|\n",
- "|GridCoverage2D[\"h...| 35| 31|\n",
- "|GridCoverage2D[\"h...|108| 44|\n",
- "|GridCoverage2D[\"h...|114| 53|\n",
- "+--------------------+---+---+\n",
- "only showing top 20 rows\n",
- "\n",
- "User Guide: https://docs.kepler.gl/docs/keplergl-jupyter\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "d99f90e2957d400a8056dd4510820aed",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "KeplerGl(data={'tiles': {'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2…"
- ]
- },
- "execution_count": 57,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sedona.table(\"wherobots.test_db.world_pop_indb_tiles\").show()\n",
- "tiledMap = SedonaKepler.create_map()\n",
- "SedonaKepler.add_df(tiledMap, sedona.table(\"wherobots.test_db.world_pop_indb_tiles\").withColumn(\"tile\", expr(\"RS_Envelope(tile)\")), name=\"tiles\")\n",
- "tiledMap"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "9c27b6d3-b71d-49b2-b03a-ebbe5b3ca6f2",
- "metadata": {},
- "source": [
- "# Population of POIs\n",
- "\n",
- "We'll join the POI dataset with the population dataset to evaluate the population of POIs."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2f40ba2f-3de8-4cd0-a423-fbb03b89c420",
- "metadata": {},
- "source": [
- "## Load POI Dataset"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "id": "67747dda-c9c2-46ec-a05e-79fb3a14fcb9",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:23.006117Z",
- "iopub.status.busy": "2025-02-04T08:19:23.005781Z",
- "iopub.status.idle": "2025-02-04T08:19:24.091316Z",
- "shell.execute_reply": "2025-02-04T08:19:24.090468Z",
- "shell.execute_reply.started": "2025-02-04T08:19:23.006091Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+\n",
- "| geometry|scalerank|featurecla| type| name|abbrev|location|gps_code|iata_code| wikipedia|natlscale|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+\n",
- "|POINT (113.935016...| 2| Airport|major| Hong Kong Int'l| HKG|terminal| VHHH| HKG|http://en.wikiped...| 150.000|\n",
- "|POINT (121.231370...| 2| Airport|major| Taoyuan| TPE|terminal| RCTP| TPE|http://en.wikiped...| 150.000|\n",
- "|POINT (4.76437693...| 2| Airport|major| Schiphol| AMS|terminal| EHAM| AMS|http://en.wikiped...| 150.000|\n",
- "|POINT (103.986413...| 2| Airport|major|Singapore Changi| SIN|terminal| WSSS| SIN|http://en.wikiped...| 150.000|\n",
- "|POINT (-0.4531566...| 2| Airport|major| London Heathrow| LHR| parking| EGLL| LHR|http://en.wikiped...| 150.000|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- }
- ],
- "source": [
- "spatialRdd = ShapefileReader.readToGeometryRDD(sedona.sparkContext, \"s3://wherobots-examples/data/ne_50m_airports\")\n",
- "poi_df = Adapter.toDf(spatialRdd, sedona)\n",
- "poi_df.show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "439abef2-110a-4f69-9816-55aa101ef112",
- "metadata": {},
- "source": [
- "## Joining POIs with out-db raster\n",
- "\n",
- "We can perform a catesian join with the single row large out-db raster table, and evaluates the population value on each point."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "id": "81cf563f-09e6-4aba-9f45-fd3793acd039",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:25.779859Z",
- "iopub.status.busy": "2025-02-04T08:19:25.779519Z",
- "iopub.status.idle": "2025-02-04T08:19:35.014875Z",
- "shell.execute_reply": "2025-02-04T08:19:35.014038Z",
- "shell.execute_reply.started": "2025-02-04T08:19:25.779835Z"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+------------------+\n",
- "| geometry|scalerank|featurecla| type| name|abbrev|location|gps_code|iata_code| wikipedia|natlscale| pop|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+------------------+\n",
- "|POINT (113.935016...| 2| Airport|major| Hong Kong Int'l| HKG|terminal| VHHH| HKG|http://en.wikiped...| 150.000| 1627.572998046875|\n",
- "|POINT (121.231370...| 2| Airport|major| Taoyuan| TPE|terminal| RCTP| TPE|http://en.wikiped...| 150.000|1459.4176025390625|\n",
- "|POINT (4.76437693...| 2| Airport|major| Schiphol| AMS|terminal| EHAM| AMS|http://en.wikiped...| 150.000|1093.3812255859375|\n",
- "|POINT (103.986413...| 2| Airport|major|Singapore Changi| SIN|terminal| WSSS| SIN|http://en.wikiped...| 150.000| 275.9463195800781|\n",
- "|POINT (-0.4531566...| 2| Airport|major| London Heathrow| LHR| parking| EGLL| LHR|http://en.wikiped...| 150.000| 53.41670227050781|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+------------------+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "data": {
- "text/plain": [
- "204"
- ]
- },
- "execution_count": 59,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "res_df = poi_df.join(sedona.table(\"wherobots.test_db.world_pop\")).withColumn(\"pop\", expr(\"RS_Value(rast, geometry)\")).drop(\"rast\")\n",
- "res_df.show(5)\n",
- "res_df.where(\"pop > 100\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "835a963a-632f-4b4e-afbc-2b770843228a",
- "metadata": {},
- "source": [
- "## Joining POIs with out-db tiles\n",
- "\n",
- "We run a spatial join using the POI and out-db raster tile dataset, and evaluates the population value on each point."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "id": "c25db656-3c63-40bf-b012-fb98e31a0dea",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:38.780618Z",
- "iopub.status.busy": "2025-02-04T08:19:38.780283Z",
- "iopub.status.idle": "2025-02-04T08:19:50.469306Z",
- "shell.execute_reply": "2025-02-04T08:19:50.468728Z",
- "shell.execute_reply.started": "2025-02-04T08:19:38.780594Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+---+---+------------------+\n",
- "| geometry|scalerank|featurecla| type| name|abbrev|location|gps_code|iata_code| wikipedia|natlscale| x| y| pop|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+---+---+------------------+\n",
- "|POINT (113.935016...| 2| Airport|major| Hong Kong Int'l| HKG|terminal| VHHH| HKG|http://en.wikiped...| 150.000|137| 28| 1627.572998046875|\n",
- "|POINT (121.231370...| 2| Airport|major| Taoyuan| TPE|terminal| RCTP| TPE|http://en.wikiped...| 150.000|141| 27|1459.4176025390625|\n",
- "|POINT (4.76437693...| 2| Airport|major| Schiphol| AMS|terminal| EHAM| AMS|http://en.wikiped...| 150.000| 86| 14|1093.3812255859375|\n",
- "|POINT (103.986413...| 2| Airport|major|Singapore Changi| SIN|terminal| WSSS| SIN|http://en.wikiped...| 150.000|133| 38| 275.9463195800781|\n",
- "|POINT (-0.4531566...| 2| Airport|major| London Heathrow| LHR| parking| EGLL| LHR|http://en.wikiped...| 150.000| 84| 15| 53.41670227050781|\n",
- "+--------------------+---------+----------+-----+----------------+------+--------+--------+---------+--------------------+---------+---+---+------------------+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "data": {
- "text/plain": [
- "204"
- ]
- },
- "execution_count": 60,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "res_df = poi_df.join(sedona.table(\"wherobots.test_db.world_pop_tiles\"), expr(\"RS_Intersects(tile, geometry)\")).withColumn(\"pop\", expr(\"RS_Value(tile, geometry)\")).drop(\"tile\")\n",
- "res_df.show(5)\n",
- "res_df.where(\"pop > 100\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "65be6bc9-4305-4f85-b72c-9a8a83e7eb8d",
- "metadata": {},
- "source": [
- "## Joining POIs with in-db tiles"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 61,
- "id": "9ca57eac-1206-4cca-8ead-10cec72ed548",
- "metadata": {
- "execution": {
- "iopub.execute_input": "2025-02-04T08:19:53.598625Z",
- "iopub.status.busy": "2025-02-04T08:19:53.598283Z",
- "iopub.status.idle": "2025-02-04T08:20:03.725153Z",
- "shell.execute_reply": "2025-02-04T08:20:03.724446Z",
- "shell.execute_reply.started": "2025-02-04T08:19:53.598600Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "+--------------------+---------+----------+-----+--------------------+------+--------+--------+---------+--------------------+---------+---+---+-----------------+\n",
- "| geometry|scalerank|featurecla| type| name|abbrev|location|gps_code|iata_code| wikipedia|natlscale| x| y| pop|\n",
- "+--------------------+---------+----------+-----+--------------------+------+--------+--------+---------+--------------------+---------+---+---+-----------------+\n",
- "|POINT (-64.702774...| 4| Airport| mid| Bermuda Int'l| BDA|terminal| TXKF| BDA|http://en.wikiped...| 50.000| 54| 24|685.7862548828125|\n",
- "|POINT (15.4465162...| 4| Airport| mid|Kinshasa N Djili ...| FIH|terminal| FZAA| FIH|http://en.wikiped...| 50.000| 91| 41|994.3622436523438|\n",
- "|POINT (-97.226769...| 4| Airport|major| Winnipeg Int'l| YWG|terminal| CYWG| YWG|http://en.wikiped...| 50.000| 38| 15|2.445089340209961|\n",
- "|POINT (80.1637759...| 4| Airport|major| Chennai Int'l| MAA|terminal| VOMM| MAA|http://en.wikiped...| 50.000|121| 33| 11405.51171875|\n",
- "|POINT (18.5976565...| 2| Airport|major| Cape Town Int'l| CPT|terminal| FACT| CPT|http://en.wikiped...| 150.000| 93| 55| 0.0|\n",
- "+--------------------+---------+----------+-----+--------------------+------+--------+--------+---------+--------------------+---------+---+---+-----------------+\n",
- "only showing top 5 rows\n",
- "\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " \r"
- ]
- },
- {
- "data": {
- "text/plain": [
- "204"
- ]
- },
- "execution_count": 61,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "res_df = poi_df.join(sedona.table(\"wherobots.test_db.world_pop_indb_tiles\"), expr(\"RS_Intersects(tile, geometry)\")).withColumn(\"pop\", expr(\"RS_Value(tile, geometry)\")).drop(\"tile\")\n",
- "res_df.show(5)\n",
- "res_df.where(\"pop > 100\").count()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e0eaf9b7-48a8-4708-bc2e-30828634d92f",
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.11.11"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/python/havasu/havasu-iceberg-raster-etl.ipynb b/python/havasu/havasu-iceberg-raster-etl.ipynb
deleted file mode 100644
index ea0b8c5..0000000
--- a/python/havasu/havasu-iceberg-raster-etl.ipynb
+++ /dev/null
@@ -1,577 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Havasu Raster ETL example\n",
- "\n",
- "In this example we demonstrate:\n",
- "\n",
- "* working with the EuroSAT raster dataset as Havasu tables\n",
- "* raster opertions \n",
- "* handling CRS transforms, and \n",
- "* benchmarking raster geometry operations\n",
- "\n",
- "\n",
- "Read more about [Havasu](https://docs.wherobots.com/latest/references/havasu/introduction/), and [WherobotsDB Raster support](https://docs.wherobots.com/latest/references/havasu/raster/raster-overview/) in the documentation."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Launch Spark Job"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from pyspark.sql import SparkSession\n",
- "from pyspark.sql.functions import expr, col\n",
- "from sedona.spark import *\n",
- "import geopandas as gpd"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Define sedona context"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "config = SedonaContext.builder().appName('havasu-iceberg-raster-etl')\\\n",
- " .config(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\")\\\n",
- " .getOrCreate()\n",
- "sedona = SedonaContext.create(config)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Load Raster Datasets"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## EuroSAT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "eurosat_path = 's3://wherobots-examples/data/eurosat_small'\n",
- "df_binary = sedona.read.format(\"binaryFile\").option(\"pathGlobFilter\", \"*.tif\").option(\"recursiveFileLookup\", \"true\").load(eurosat_path)\n",
- "df_geotiff = df_binary.withColumn(\"rast\", expr(\"RS_FromGeoTiff(content)\")).withColumn(\"name\", expr(\"reverse(split(path, '/'))[0]\")).select(\"name\", \"length\", \"rast\")\n",
- "df_geotiff.show(5, False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Save Raster Datasets to Havasu"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE NAMESPACE IF NOT EXISTS wherobots.test_db\")\n",
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.eurosat_ms\")\n",
- "df_geotiff.coalesce(16).writeTo(\"wherobots.test_db.eurosat_ms\").create()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Save another copy of EuroSAT partitioned by SRID"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.eurosat_ms_srid\")\n",
- "df_rast_havasu = sedona.table(\"wherobots.test_db.eurosat_ms\")\n",
- "df_rast_havasu.withColumn(\"srid\", expr(\"RS_SRID(rast) as srid\"))\\\n",
- " .sort('srid')\\\n",
- " .write.format(\"havasu.iceberg\").partitionBy(\"srid\")\\\n",
- " .saveAsTable(\"wherobots.test_db.eurosat_ms_srid\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Reload Havasu Rasters"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu = sedona.table(\"wherobots.test_db.eurosat_ms\")\n",
- "df_rast_havasu_srid = sedona.table('wherobots.test_db.eurosat_ms_srid')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Test Raster Functions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Basic Raster Property Accessors"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu.selectExpr(\"name\", \"RS_Envelope(rast) as env\", \"RS_Metadata(rast) as meta\").show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Pixel Data Accessors"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu.selectExpr(\"name\", \"RS_Value(rast, ST_Centroid(RS_Envelope(rast))) as centroid_val\").show(5, False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Band Accessors"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu.selectExpr(\"name\", \"RS_BandAsArray(rast, 1) as band1\", \"RS_BandAsArray(rast, 2) as band2\", \"RS_BandAsArray(rast, 3) as band3\").show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Preprocessing for DeepSatV2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_extra_features = df_rast_havasu\\\n",
- " .withColumn(\"band_red\", expr(\"RS_BandAsArray(rast, 4)\"))\\\n",
- " .withColumn(\"band_green\", expr(\"RS_BandAsArray(rast, 3)\"))\\\n",
- " .withColumn(\"band_nir\", expr(\"RS_BandAsArray(rast, 8)\"))\\\n",
- " .withColumn(\"band_swir1\", expr(\"RS_BandAsArray(rast, 12)\"))\\\n",
- " .withColumn(\"band_swir2\", expr(\"RS_BandAsArray(rast, 13)\"))\\\n",
- " .withColumn(\"band_ndwi\", expr(\"RS_NormalizedDifference(band_green, band_nir)\"))\\\n",
- " .withColumn(\"band_mndwi\", expr(\"RS_NormalizedDifference(band_green, band_swir1)\"))\\\n",
- " .withColumn(\"band_ndmi\", expr(\"RS_NormalizedDifference(band_nir, band_swir1)\"))\\\n",
- " .withColumn(\"band_ndvi\", expr(\"RS_NormalizedDifference(band_nir, band_red)\"))\\\n",
- " .withColumn(\"band_awei\", expr(\"RS_Subtract(RS_MultiplyFactor(RS_Subtract(band_green, band_swir1), 4), RS_Add(RS_MultiplyFactor(band_nir, 0.25), RS_MultiplyFactor(band_swir2, 2.75)))\"))\\\n",
- " .withColumn(\"band_builtup\", expr(\"RS_NormalizedDifference(band_swir1, band_nir)\"))\\\n",
- " .withColumn(\"band_rvi\", expr(\"RS_Divide(band_nir, RS_LogicalOver(band_red, RS_Array(array_size(band_red), 1e-12)))\"))\\\n",
- " .selectExpr(\"name\", \"RS_Mean(band_ndwi) as mean_ndwi\", \"RS_Mean(band_mndwi) as mean_mndwi\", \"RS_Mean(band_ndmi) as mean_ndmi\", \"RS_Mean(band_ndvi) as mean_ndvi\", \"RS_Mean(band_awei) as mean_awei\", \"RS_Mean(band_builtup) as mean_builtup\", \"RS_Mean(band_rvi) as mean_rvi\")\n",
- "df_extra_features.show(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_extra_features = df_rast_havasu\\\n",
- " .withColumn(\"ndvi\", expr(\"RS_MapAlgebra(rast, 'd', 'out = (rast[3] - rast[7]) / (rast[3] + rast[7]);', null)\"))\\\n",
- " .withColumn(\"awei\", expr(\"RS_MapAlgebra(rast, 'd', 'out = (0.25 * rast[7] + 2.75 * rast[12]) - 4 * (rast[11] - rast[2]);', null)\"))\\\n",
- " .withColumn(\"rvi\", expr(\"RS_MapAlgebra(rast, 'd', 'out = rast[7] / max(rast[3], 0.000001);', null)\"))\\\n",
- " .withColumn(\"mean_ndvi\", expr(\"RS_Mean(RS_BandAsArray(ndvi, 1))\"))\\\n",
- " .withColumn(\"mean_awei\", expr(\"RS_Mean(RS_BandAsArray(awei, 1))\"))\\\n",
- " .withColumn(\"mean_rvi\", expr(\"RS_Mean(RS_BandAsArray(rvi, 1))\"))\n",
- "df_extra_features.show(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_extra_features.where(\"mean_awei > 0.5\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Data Visualization"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We'll visualize the bounding boxes of the rasters in EuroSAT. Here we can see the importance of handling the CRS of rasters properly.\n",
- "\n",
- "* `df_rast_env` contains envelopes of rasters in EuroSAT\n",
- "* `df_rast_env_srid` contains envelopes of rasters in EuroSAT transformed to CRS:4326 (EPSG:4326 in lon-lat axis order)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_env = df_rast_havasu.selectExpr('name', \"RS_Envelope(rast) as env\", \"RS_SRID(rast) as srid\")\n",
- "\n",
- "df_rast_env_4326 = df_rast_havasu.selectExpr('name', \"RS_Envelope(rast) as env\", \"RS_SRID(rast) as srid\")\\\n",
- " .withColumn(\"env_4326\", expr(\"ST_Transform(env, concat('epsg:', srid), 'epsg:4326')\"))\\\n",
- " .select(\"name\", \"env_4326\", \"srid\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's plot the datasets. We plot the transformed envelopes of the rasters, and color the geometries by the original SRID of the rasters. We know that the CRS of the rasters are in UTM, so they appears to be grouped by vertical stripes."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "rasterMap_4326 = SedonaKepler.create_map()\n",
- "SedonaKepler.add_df(rasterMap_4326, df_rast_env_4326, name=\"raster-bounds\")\n",
- "rasterMap_4326"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can see that the rasters in `df_rast_env` are not plotted correctly because the rasters are in various UTM CRS, and it is not meaningful to plot rasters in different CRS together.\n",
- "\n",
- "The reason why plotting the envelopes of rasters without considering their CRS results in a long stripe is that the CRS of the rasters are in UTM, and rasters in different UTM zones have the same coordinate range since they share the same false easting and northing."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "gdf_rast_env = df_rast_env.toPandas()\n",
- "gdf_rast_env = gpd.GeoDataFrame(gdf_rast_env, geometry='env')\n",
- "gdf_rast_env['boundary'] = gdf_rast_env.boundary\n",
- "gdf_rast_env.set_geometry('boundary', inplace=True)\n",
- "gdf_rast_env.plot(column='srid')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Use a better partitioner for faster range query"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's use the H3 cell ID of the centroid of the raster in EPSG:4326 to partition the dataset. This will result in a better partitioning scheme for range query."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu_h3 = df_rast_havasu\\\n",
- " .withColumn(\"centroid\", expr(\"ST_Transform(ST_Centroid(RS_Envelope(rast)), concat('epsg:', RS_SRID(rast)), 'epsg:4326')\"))\\\n",
- " .withColumn(\"h3_cell_id\", expr(\"array_max(ST_H3CellIDs(centroid, 1, false))\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we plot the centroid of rasters using different colors for different H3 cell IDs, we can see that the rasters are partitioned into different H3 cells."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "gdf_rast_havasu_h3 = gpd.GeoDataFrame(df_rast_havasu_h3.select(\"centroid\", \"h3_cell_id\").toPandas(), geometry='centroid', crs='EPSG:4326')\n",
- "gdf_rast_havasu_h3.plot(column='h3_cell_id', cmap='flag', markersize=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's save the dataset partitioned by H3 cell ID and reload it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.eurosat_ms_h3\")\n",
- "df_rast_havasu_h3.sort(\"h3_cell_id\").write.format(\"havasu.iceberg\").partitionBy(\"h3_cell_id\").saveAsTable(\"wherobots.test_db.eurosat_ms_h3\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_rast_havasu_h3 = sedona.table('wherobots.test_db.eurosat_ms_h3')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Benchmarking Raster Functions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is just a simple benchmark running on EuroSAT dataset. It could give the user a rough idea of how havasu in-db raster performs compared to GeoTiff when processing lots of tiny raster images."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import time\n",
- "\n",
- "def benchmark_query(df_dict, bench_func, num_runs=1):\n",
- " cost_dict = {}\n",
- " for name, df in df_dict.items():\n",
- " print(f\"Running benchmark for {name}\")\n",
- " cost_dict[name] = []\n",
- " for i in range(1, num_runs + 1):\n",
- " print(f\"Run #{i} for {name}\")\n",
- " start = time.time()\n",
- " result = bench_func(df)\n",
- " end = time.time()\n",
- " cost = end - start\n",
- " print(f\"Run #{i} for {name} took {cost} seconds, result: {result}\")\n",
- " cost_dict[name].append(cost)\n",
- " # print summary\n",
- " for name, costs in cost_dict.items():\n",
- " print(f\"Summary for {name} - runs: {len(costs)}, mean: {sum(costs)/len(costs)}, min: {min(costs)}, max: {max(costs)}\")\n",
- " return cost_dict"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df_dict = {\n",
- " 'havasu': df_rast_havasu,\n",
- " 'havasu_srid': df_rast_havasu_srid,\n",
- " 'havasu_h3': df_rast_havasu_h3,\n",
- " 'geotiff': df_geotiff\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Scanning the entire dataset and extract basic raster properties"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def bench_func(df):\n",
- " return df.withColumn(\"num_bands\", expr(\"RS_NumBands(rast)\")).where(\"num_bands IS NOT NULL\").count()\n",
- "\n",
- "benchmark_query(df_dict, bench_func, num_runs=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Scanning the entire dataset and extract bands"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def bench_func(df):\n",
- " return df.selectExpr(\"name\", \"RS_BandAsArray(rast, 1) as band1\", \"RS_BandAsArray(rast, 2) as band2\")\\\n",
- " .selectExpr(\"RS_NormalizedDifference(band1, band2) as band_nd\")\\\n",
- " .where(\"array_size(band_nd) > 0\")\\\n",
- " .count()\n",
- "\n",
- "benchmark_query(df_dict, bench_func, num_runs=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Scanning the entire dataset and extract pixel values"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def bench_func(df):\n",
- " return df.selectExpr(\"RS_Value(rast, ST_Centroid(RS_Envelope(rast))) as centroid_val\")\\\n",
- " .where(\"centroid_val IS NOT NULL\")\\\n",
- " .count()\n",
- " \n",
- "benchmark_query(df_dict, bench_func, num_runs=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Range query"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We run several range queries on the EuroSAT dataset using the following query windows. The query windows were specified as rectangles in EPSG:4326."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "query_windows = {\n",
- " 'spain_madrid': 'ST_SetSRID(ST_PolygonFromEnvelope(-4.7803,39.5882, -2.7782,40.9276), 4326)',\n",
- " 'cesko_praha': 'ST_SetSRID(ST_PolygonFromEnvelope(13.2747,49.2297, 16.3189,51.0516), 4326)',\n",
- " 'france_paris': 'ST_SetSRID(ST_PolygonFromEnvelope(1.299,48.156, 3.566,49.575), 4326)',\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def bench_query_func(df, qw_expr):\n",
- " return df.where(f\"RS_Intersects(rast, {qw_expr})\").count()\n",
- "\n",
- "for qw_name, qw_exr in query_windows.items():\n",
- " print(f\"Running benchmark using query window {qw_name}\")\n",
- " benchmark_query(df_dict, lambda df: bench_query_func(df, qw_exr), num_runs=1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.11"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/scala/sedona-maven-example/.gitignore b/scala/sedona-maven-example/.gitignore
deleted file mode 100644
index 93faf13..0000000
--- a/scala/sedona-maven-example/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/dependency-reduced-pom.xml
-/target/
diff --git a/scala/sedona-maven-example/pom.xml b/scala/sedona-maven-example/pom.xml
deleted file mode 100644
index 10d29fb..0000000
--- a/scala/sedona-maven-example/pom.xml
+++ /dev/null
@@ -1,190 +0,0 @@
-
- 4.0.0
- com.wherobots
- sedonadb-example
- 0.0.1
-
- ${project.groupId}:${project.artifactId}
- Maven Example for WherobotsDB
- jar
-
-
- UTF-8
- provided
- 1.6.0-28.2
- compile
- 1.19.0
- 0.14.3
- 3.5.3
- 3.5
- 2.12
- 1.5.0
- 3.3.4
-
-
-
-
- org.apache.spark
- spark-core_${scala.compat.version}
- ${spark.version}
- ${dependency.scope}
-
-
- org.apache.spark
- spark-sql_${scala.compat.version}
- ${spark.version}
- ${dependency.scope}
-
-
- com.wherobots
- sedona-spark-shaded-${spark.compat.version}_${scala.compat.version}
- ${sedona.version}
- ${dependency.scope}
-
-
- com.wherobots.havasu
- iceberg-spark-runtime-${spark.compat.version}_${scala.compat.version}
- ${sedona.version}
- ${dependency.scope}
-
-
- com.wherobots
- wherobots-tools-core
- ${sedona.version}
- ${dependency.scope}
-
-
- org.datasyslab
- geotools-wrapper
- ${geotoolswrapper.version}
- ${dependency.scope}
-
-
- org.apache.hadoop
- hadoop-aws
- ${hadoop.version}
- ${dependency.scope}
-
-
- junit
- junit
- 4.13.1
- test
-
-
-
-
- wherobots-repo
- file:///opt/wherobots/repository
-
-
- maven-central
- Maven Central Repository
- https://repo.maven.apache.org/maven2/
-
- false
-
-
- true
-
-
-
- maven2-repository.dev.java.net
- Java.net repository
- https://download.java.net/maven/2
-
-
- osgeo
- OSGeo Release Repository
- https://repo.osgeo.org/repository/release/
-
- false
-
-
- true
-
-
-
-
-
- src/main/scala
-
-
- net.alchim31.maven
- scala-maven-plugin
- 3.2.1
-
-
- scala-compile-first
- process-resources
-
- add-source
- compile
-
-
-
- -dependencyfile
- ${project.build.directory}/.scala_dependencies
-
-
-
-
- scala-test-compile
- process-test-resources
-
- testCompile
-
-
-
- -dependencyfile
- ${project.build.directory}/.scala_dependencies
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.1
-
- 1.8
- 1.8
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.1
-
-
- package
-
- shade
-
-
-
-
-
- *:*
-
- META-INF/*.SF
- META-INF/*.DSA
- META-INF/*.RSA
-
-
-
-
-
-
-
-
-
-
- src/test/resources/
-
-
-
-
-
diff --git a/scala/sedona-maven-example/src/main/scala/com/wherobots/sedona/SedonaDbExample.scala b/scala/sedona-maven-example/src/main/scala/com/wherobots/sedona/SedonaDbExample.scala
deleted file mode 100644
index e43295f..0000000
--- a/scala/sedona-maven-example/src/main/scala/com/wherobots/sedona/SedonaDbExample.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.wherobots.sedona
-
-import org.apache.log4j.{Level, Logger}
-import org.apache.sedona.core.formatMapper.shapefileParser.ShapefileReader
-import org.apache.sedona.spark.SedonaContext
-import org.apache.sedona.sql.utils.Adapter
-import org.apache.spark.sql.SaveMode
-import org.apache.spark.sql.functions.desc
-
-
-object SedonaDbExample extends App {
-
- Logger.getRootLogger.setLevel(Level.WARN)
- Logger.getLogger("org.apache").setLevel(Level.WARN)
- Logger.getLogger("com").setLevel(Level.WARN)
- Logger.getLogger("akka").setLevel(Level.WARN)
-
- val s3BucketName = "wherobots-examples"
- val config = SedonaContext.builder()
- .config(s"spark.hadoop.fs.s3a.bucket.$s3BucketName.aws.credentials.provider","org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
- .getOrCreate()
- val sedona = SedonaContext.create(config)
- val sc = sedona.sparkContext
-
- // Read the countries shapefiles from S3
- val countries = ShapefileReader.readToGeometryRDD(sc, s"s3://$s3BucketName/data/ne_50m_admin_0_countries_lakes/")
- // Convert the Spatial RDD to a Spatial DataFrame using the Adapter
- val countries_df = Adapter.toDf(countries, sedona)
- countries_df.createOrReplaceTempView("country")
- countries_df.printSchema()
-
- // Read the airports shapefiles from S3
- val airports = ShapefileReader.readToGeometryRDD(sc, s"s3://$s3BucketName/data/ne_50m_airports/")
- // Convert the Spatial RDD to a Spatial DataFrame using the Adapter
- val airports_df = Adapter.toDf(airports, sedona)
- airports_df.createOrReplaceTempView("airport")
- airports_df.printSchema()
-
- // Run a spatial join query to find airports in each country
- val result = sedona.sql("SELECT c.geometry as country_geom, c.NAME_EN, a.geometry as airport_geom, a.name FROM country c, airport a WHERE ST_Contains(c.geometry, a.geometry)")
- // Aggregate the results to find the number of airports in each country
- val aggregateResult = result.groupBy("NAME_EN", "country_geom").count()
- aggregateResult.orderBy(desc("count")).show()
-
- // Write the results to a GeoParquet file
- aggregateResult.write.format("geoparquet").mode(SaveMode.Overwrite).save("airport_country.parquet")
-}
diff --git a/scala/sedona-maven-example/src/test/resources/.gitignore b/scala/sedona-maven-example/src/test/resources/.gitignore
deleted file mode 100644
index 764e830..0000000
--- a/scala/sedona-maven-example/src/test/resources/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.DS_Store
-real-*
diff --git a/scala/sedona-maven-example/src/test/resources/scalastyle_config.xml b/scala/sedona-maven-example/src/test/resources/scalastyle_config.xml
deleted file mode 100644
index 6a95f66..0000000
--- a/scala/sedona-maven-example/src/test/resources/scalastyle_config.xml
+++ /dev/null
@@ -1,187 +0,0 @@
-
- Scalastyle standard configuration
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/scala/wherobots-db/havasu-iceberg-geometry-etl-scala.ipynb b/scala/wherobots-db/havasu-iceberg-geometry-etl-scala.ipynb
deleted file mode 100644
index dfcfe31..0000000
--- a/scala/wherobots-db/havasu-iceberg-geometry-etl-scala.ipynb
+++ /dev/null
@@ -1,525 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "eaf79258-6c1d-461e-bc35-1267b15f30a6",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Havasu Geometry ETL Example - Scala\n",
- "\n",
- "This notebook demonstrates working with [Havasu](https://docs.wherobots.com/latest/references/havasu/introduction/), a spatial table format, using a taxi pickup dataset."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e7588b84-c8ea-4ad2-886a-78b962423931",
- "metadata": {},
- "outputs": [],
- "source": [
- "%%init_spark\n",
- "launcher.conf.set(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fb738fb5-68c1-4de1-8b85-da815f952e7a",
- "metadata": {},
- "outputs": [],
- "source": [
- "import org.apache.sedona.spark.SedonaContext"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a05688e6-cc34-41a4-acfc-3d547bd9bf53",
- "metadata": {},
- "source": [
- "# Define sedona context"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "20d8806e-8356-44f0-8981-dae801fb5191",
- "metadata": {},
- "outputs": [],
- "source": [
- "val sedona = SedonaContext.create(spark)\n",
- "val sc = sedona.sparkContext"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "66e3a4f9-8bbb-48ef-a557-3478382f6ea5",
- "metadata": {},
- "source": [
- "# Load taxi pickup records to Sedona"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2ccfff4a-84d3-40e0-86b8-542a0d08301f",
- "metadata": {},
- "outputs": [],
- "source": [
- "val taxiDf = sedona.read.format(\"csv\").option(\"header\",\"true\").option(\"delimiter\", \",\").load(\"s3://wherobots-examples/data/nyc-taxi-data.csv\");\n",
- "val taxiDf_geom = taxiDf.selectExpr(\"ST_Point(CAST(Start_Lon AS Decimal(24,20)), CAST(Start_Lat AS Decimal(24,20))) AS pickup\", \"Trip_Pickup_DateTime\", \"Payment_Type\", \"Fare_Amt\");\n",
- "val taxiDf_geom_filtered = taxiDf_geom.filter(col(\"pickup\").isNotNull);\n",
- "taxiDf_geom_filtered.show(5);\n",
- "taxiDf_geom_filtered.createOrReplaceTempView(\"taxiDf\");"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "094dfa53-fa75-472e-8293-230e90284390",
- "metadata": {},
- "source": [
- "# Manage taxi pickup data using Havasu"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1941b835-9001-40df-9959-9b30819b4f2c",
- "metadata": {},
- "source": [
- "Havasu is a data lake for geospatial data. User can manage their datasets as Havasu tables."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1970abf4-b879-4241-a0b4-5d183e42805e",
- "metadata": {},
- "source": [
- "## Save DataFrame to a Havasu Table"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4857c2a4-10c1-4fae-97ee-30ee7744995c",
- "metadata": {
- "is_executing": true
- },
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE NAMESPACE IF NOT EXISTS wherobots.test_db\")\n",
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.taxi\")\n",
- "taxiDf_geom_filtered.writeTo(\"wherobots.test_db.taxi\").create()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "daa30e17-c54c-4602-b506-6135db535b04",
- "metadata": {},
- "source": [
- "## Read taxi pickup records from Havasu Table"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f884111a-51a1-4b47-ab7e-1f7daf00051b",
- "metadata": {},
- "outputs": [],
- "source": [
- "val taxiDf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxiDf.show(5)\n",
- "print(\"total count: \" + taxiDf.count())"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "86d6a55c-6395-4fb8-afbc-392538c2d34b",
- "metadata": {},
- "source": [
- "### Note that the pickup column is a geometry column."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a4adb3f9-ba73-4dd7-995e-52423296989e",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxiDf.printSchema()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "848462db-59b3-4ca6-b0fe-538b50c1f5fb",
- "metadata": {},
- "source": [
- "### Seamless integration with Sedona Enterprise"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "216369d6-0300-4ed9-a007-d860e8e49128",
- "metadata": {},
- "source": [
- "We can directly apply Sedona ST_ functions to pickup column."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a9a3f3b4-7927-42ca-936c-7c15d598a3dd",
- "metadata": {},
- "outputs": [],
- "source": [
- "taxiDf.withColumn(\"buf\", expr(\"ST_Buffer(pickup, 1e-4)\")).show(5)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e3218528-3fe7-4e70-9d6e-d63715971f78",
- "metadata": {},
- "source": [
- "## ACID Properties of Havasu Table"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "eb2014d3-e17f-4126-965a-a1732ef413ef",
- "metadata": {},
- "source": [
- "Havasu supports all ACID properties on a on-disk table, we can append data or modify the table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7ec755e3-ea4f-4bc8-a183-a736539bc9c2",
- "metadata": {},
- "outputs": [],
- "source": [
- "val bufDf = taxiDf.withColumn(\"pickup\", expr(\"ST_Buffer(pickup, 1e-4)\"))\n",
- "bufDf.writeTo(\"wherobots.test_db.taxi\").append()\n",
- "val countAppend = sedona.table(\"wherobots.test_db.taxi\").count()\n",
- "print(\"total count after append: \" + countAppend)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "489c79d9-dd14-43c2-9a9f-205c58da71ca",
- "metadata": {},
- "source": [
- "We can also use SQL to manipulate data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "51d091a4-dbe6-45e7-b23d-41480a6b4b6b",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi\").show(5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4c69a9f5-74af-4d45-9681-1e9f3e69ec71",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"INSERT INTO wherobots.test_db.taxi VALUES (ST_Point(10, 20), '1/26/09 10:20', 'Cash', 3.14)\")\n",
- "sedona.sql(\"INSERT INTO wherobots.test_db.taxi VALUES (ST_Point(10, 20), '1/26/09 10:20', 'Online', 31.4)\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6721ebb3-fd35-41df-8103-0da6e50314bc",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"UPDATE wherobots.test_db.taxi SET Fare_Amt = 314 WHERE ST_Intersects(pickup, ST_Point(10, 20)) AND Payment_Type = 'Online'\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "080ef02f-a648-4d8f-b882-56902ae57f4c",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DELETE FROM wherobots.test_db.taxi WHERE Payment_Type = 'Online'\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi WHERE ST_Intersects(pickup, ST_Point(10, 20))\").show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c68184a2-a331-4386-9b52-e120f78ff458",
- "metadata": {},
- "source": [
- "## Time Travel"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "691713b1-e4fd-4f94-8a34-f2c5812797de",
- "metadata": {},
- "source": [
- "We can view table history and read a particular version of the table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "301b9120-40b5-4061-a8a5-d4252381fefe",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi.history ORDER BY made_current_at\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7fc75b09-4093-4bdf-b4b6-de6ee3002ffd",
- "metadata": {},
- "outputs": [],
- "source": [
- "val snapshots = sedona.sql(\"SELECT * FROM wherobots.test_db.taxi.history ORDER BY made_current_at\").collect()\n",
- "val snapshot_1 = snapshots(1).getLong(1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bda39783-ed36-40f0-aa35-851e90000258",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.table(\"wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0cea85c2-6808-43d2-9a09-e7d95e98d0d6",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.read.option(\"snapshot-id\", snapshot_1).table(\"wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fa1ffe7c-6e87-43cd-97b6-9825a961a5d1",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(s\"SELECT * FROM wherobots.test_db.taxi VERSION AS OF $snapshot_1\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "aa98acc0-c465-498c-96b3-46e96639bfce",
- "metadata": {},
- "source": [
- "Now let's roll back to version 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "06711614-ea1f-460f-b7ed-ae24db17a8aa",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(s\"CALL wherobots.system.rollback_to_snapshot('wherobots.test_db.taxi', $snapshot_1)\")\n",
- "sedona.sql(\"SELECT * FROM wherobots.test_db.taxi\").count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "6ca47a6e-0a09-47fd-85de-07916f883bb8",
- "metadata": {},
- "source": [
- "## Optimize table for faster range query"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2f19040f-479e-4b88-a6b4-86371dd11c90",
- "metadata": {},
- "source": [
- "We run a small range query on the dataset to see how many records we've scanned"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2fd23bf9-0a84-47a6-8f14-5f05ab5aac7d",
- "metadata": {},
- "outputs": [],
- "source": [
- "val predicate = \"ST_Intersects(ST_PolygonFromEnvelope(-73.970730, 40.767844, -73.965615, 40.769217), pickup)\"\n",
- "val taxiDf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxiDf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "cad271ba-50a9-40d6-a6ce-7380a449404c.png": {
- "image/png": "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AgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwIIIIAAAgggkCBAoJUAxGoEEEAAAQQQQCBUgEArVI58CCCAAAIIIIBAggCBVgIQqxFAAAEEEEAAgVABAq1QOfIhgAACCCCAAAIJAgRaCUCsRgABBBBAAAEEQgUItELlyIcAAggggAACCCQIEGglALEaAQQQQAABBBAIFSDQCpUjHwII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"
- }
- },
- "cell_type": "markdown",
- "id": "bf1aa69c-9d60-4031-a374-cdd8ac2409fe",
- "metadata": {},
- "source": [
- "We can inspect the metrics data and found that Spark scanned all the data to answer this query\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1a0559c5-76e6-4a48-96f3-e74b753a8615",
- "metadata": {},
- "source": [
- "### CREATE SPATIAL INDEX\n",
- "\n",
- "We can run `CREATE SPATIAL INDEX` on the table to sort the records by spatial proximity. Havasu supports sorting the geometry values by their Hilbert index."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "32aa1e93-c8d4-446d-b8c1-96740352aebf",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"CREATE SPATIAL INDEX FOR wherobots.test_db.taxi USING hilbert(pickup, 16) OPTIONS map('target-file-size-bytes', '1000000')\").show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0e9dfdda-2bcc-4c60-b0fb-3660b12f3425",
- "metadata": {},
- "outputs": [],
- "source": [
- "val taxiDf = sedona.table(\"wherobots.test_db.taxi\")\n",
- "taxiDf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "262fa7c9-9098-4376-bd1a-191acc686927.png": {
- "image/png": "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"
- }
- },
- "cell_type": "markdown",
- "id": "e9089ff5-3185-436f-b3c8-7f1750fd1f5a",
- "metadata": {},
- "source": [
- "The same query scanned less data, this is because the spatial filter pushdown works better on sorted tables.\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5931f9ab-34ed-4c60-8c6b-8f2673d84c21",
- "metadata": {},
- "source": [
- "### Sorting by geohash value\n",
- "\n",
- "We can sort the pickup column by their geohash values and write them into 30 files."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "08722505-8aee-43ea-b3b2-7fe5568727ca",
- "metadata": {},
- "outputs": [],
- "source": [
- "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.taxi_sorted\")\n",
- "val sortedTaxiDf = taxiDf.withColumn(\"geohash\", expr(\"ST_GeoHash(ST_Centroid(pickup), 20)\"))\n",
- " .sort(col(\"geohash\"))\n",
- " .drop(\"geohash\")\n",
- "sortedTaxiDf.write.option(\"target-file-size-bytes\", \"1000000\").format(\"havasu.iceberg\").saveAsTable(\"wherobots.test_db.taxi_sorted\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e9c4db98-16bf-4ebd-9244-5fb8a369efb1",
- "metadata": {},
- "source": [
- "We run the same query on the sorted table, the result is identical with running on the original table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "744b925f-68da-469d-9c3f-f4fdf7e0c8df",
- "metadata": {},
- "outputs": [],
- "source": [
- "val sortedTaxiDf = sedona.table(\"wherobots.test_db.taxi_sorted\")\n",
- "sortedTaxiDf.where(predicate).count()"
- ]
- },
- {
- "attachments": {
- "7972a37f-ae45-45d1-baa6-5c3c282e0a19.png": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAArQAAAIUCAYAAADrIr80AAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAACtKADAAQAAAABAAACFAAAAABu7sNnAABAAElEQVR4AexdB7gUNRe9NBWk9947KAhSFAVFsICgKCogooAgCEoHFVGkWEDpWFAQEKWDCnZEBZHiDwpSBeldeu/8OXkvQ3a2vN19y/Pte+d+3+7MZJJMcpKZObm5uZPishKhEAEiQASIABEgAkSACBCBKEUgZZSWm8UmAkSACBABIkAEiAARIAIaARJadgQiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABEgoWUfIAJEgAgQASJABIgAEYhqBEhoo7r5WHgiQASIABEgAkSACBABElr2ASJABIgAESACRIAIEIGoRoCENqqbj4UnAkSACBABIkAEiAARIKFlHyACRIAIEAEiQASIABGIagRIaKO6+Vh4IkAEiAARIAJEgAgQARJa9gEiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABEgoWUfIAJEgAgQASJABIgAEYhqBEhoo7r5WHgiQASIABEgAkSACBABElr2ASJABIgAESACRIAIEIGoRoCENqqbj4UnAkSACBABIkAEiAARIKFlHyACRIAIEAEiQASIABGIagRIaKO6+Vh4IkAEiAARIAJEgAgQARJa9gEiQASIABEgAkSACBCBqEaAhDaqm4+FJwJEgAgQASJABIgAESChZR8gAkSACBABIkAEiAARiGoESGijuvlYeCJABIgAESACRIAIEAESWvYBIkAEiAARIAJEgAgQgahGgIQ2qpuPhScCRIAIEAEiQASIABFInRwhOHpeZN5+kd8PiWw6KXLwnMily8kRCdaZCBABIkAEiEDyQiBl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nkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJABIgAESACJLTsA0SACBABIkAEiAARIAJRjQAJbVQ3HwtPBIgAESACRIAIEAEiQELLPkAEiAARIAJEgAgQASIQ1QiQ0EZ187HwRIAIEAEiQASIABEgAiS07ANEgAgQASJABIgAESACUY0ACW1UNx8LTwSIABEgAkSACBABIkBCyz5ABIgAESACRIAIEAEiENUIkNBGdfOx8ESACBABIkAEiAARIAIktOwDRIAIEAEiQASIABEgAlGNAAltVDcfC08EiAARIAJEgAgQASJAQss+QASIABEgAkSACBABIhDVCJDQRnXzsfBEgAgQASJA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qkmpY9fuRn8kBBBAAAEEEGh4geRf7YbPHzlAAAEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQQCBRgIA2kYeZCCCAAAIIIIAAAqELENCGXkLkDwEEEEAAAQQQ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"
- }
- },
- "cell_type": "markdown",
- "id": "8e91f9a4-4d7b-4f5c-9ca1-13e3ab700398",
- "metadata": {},
- "source": [
- "The same query scanned less data, this is because the spatial filter pushdown works better on sorted tables.\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8c36815b-d295-4a3a-ae29-1e9cf778858d",
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Scala",
- "language": "scala",
- "name": "spylon-kernel"
- },
- "language_info": {
- "codemirror_mode": "text/x-scala",
- "file_extension": ".scala",
- "help_links": [
- {
- "text": "MetaKernel Magics",
- "url": "https://metakernel.readthedocs.io/en/latest/source/README.html"
- }
- ],
- "mimetype": "text/x-scala",
- "name": "scala",
- "pygments_lexer": "scala",
- "version": "0.4.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/scala/wherobots-db/tile-generation-example-scala.ipynb b/scala/wherobots-db/tile-generation-example-scala.ipynb
deleted file mode 100644
index 52e2f96..0000000
--- a/scala/wherobots-db/tile-generation-example-scala.ipynb
+++ /dev/null
@@ -1,268 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "5240b24e-7c77-4a2a-8191-fda9f2fd6e47",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Introduction to `VTiles` for WherobotsDB\n",
- "\n",
- "In this notebook we will create PMTiles vector tiles for rendering maps using building and road data from the Overture Maps dataset in the Wherobots Open Data Catalog."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "971dd764-b70a-4e0d-80a2-434c682ed2e3",
- "metadata": {
- "tags": []
- },
- "source": [
- "## Introduction To Vector Tiles\n",
- "\n",
- "Vector tiles provide performant rendering of map data for large vector feature datasets across large regions and zoom\n",
- "levels. Here’s why, and when, they should be used:\n",
- "\n",
- "* Vector tiles are designed for use in web maps, mobile apps, and desktop GIS software.\n",
- "* WherobotsDB makes it easy and affordable to generate vector tiles at a planetary scale.\n",
- "* By rendering vector tiles directly, the interactive map experience is more responsive and scalable for large datasets\n",
- " than rendering feature formats (e.g., GeoJSON) directly and allows developers to customize the display, which is\n",
- " otherwise impossible with raster tiles."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "eb344c65-62dd-42f5-bb73-eb4bdf18fb5e",
- "metadata": {},
- "source": [
- "## How To Generate Vector Tiles"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a9540d21-0205-4ed3-9b40-6b859a1f445c",
- "metadata": {},
- "source": [
- "### Start a Sedona Session\n",
- "\n",
- "As always, begin by starting a Sedona context"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "37a8ae86-c364-4d65-8b7b-402dd75150c4",
- "metadata": {},
- "outputs": [],
- "source": [
- "import org.apache.sedona.spark.SedonaContext\n",
- "\n",
- "val config = SedonaContext.builder().getOrCreate()\n",
- "val sedona = SedonaContext.create(config)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d3bf7649-2a35-43bb-9cb8-690426e2ad72",
- "metadata": {},
- "source": [
- "### Load Feature Data\n",
- "\n",
- "Create a Spatial DataFrame with a geometry column and a layer column. The geometry column contains the features to render in the\n",
- "map. The layer column is a string that describes the grouping the feature should be in. Records within the same layer\n",
- "can be styled together, independently of other layers. In this case example features that represent buildings are in the buildings layer and those representing roads are in the roads layer.\n",
- "\n",
- "The first cell that follows gives some variable to control where we generate tiles for. The default is a small town in Washington: Issaquah."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "86cf7fd1-1f6c-4836-81e8-bde0b67b9ce0",
- "metadata": {},
- "outputs": [],
- "source": [
- "import org.apache.spark.sql.sedona_sql.expressions.st_constructors.ST_GeomFromText\n",
- "import org.apache.spark.sql.sedona_sql.expressions.st_predicates.ST_Intersects\n",
- "import org.apache.spark.sql.functions.{lit, col}\n",
- "\n",
- "// Set to False to generate tiles for the entire dataset, true to generate only for regionWkt area\n",
- "val filter = true\n",
- "val regionWkt = \"POLYGON ((-122.097931 47.538528, -122.048836 47.566566, -121.981888 47.510012, -122.057076 47.506302, -122.097931 47.538528))\"\n",
- "val filterExpression = ST_Intersects(col(\"geometry\"), ST_GeomFromText(lit(regionWkt)))"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c075a394",
- "metadata": {
- "vscode": {
- "languageId": "plaintext"
- }
- },
- "source": [
- "Next, we create the buildings Spatial DataFrame using the Overture buildings table from the Wherobots Open Data Catalog."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d57b9c15-bf60-47b7-8b20-37be6c581af3",
- "metadata": {},
- "outputs": [],
- "source": [
- "import org.apache.spark.sql.functions.element_at\n",
- "\n",
- "val buildingsDf = sedona.table(\"wherobots_open_data.overture_2024_02_15.buildings_building\")\n",
- " .select(\n",
- " col(\"geometry\"),\n",
- " lit(\"buildings\").alias(\"layer\"),\n",
- " element_at(col(\"sources\"), 1)(\"dataset\").alias(\"source\")\n",
- " )\n",
- "\n",
- "buildingsDf.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "8e3ebc59",
- "metadata": {
- "vscode": {
- "languageId": "plaintext"
- }
- },
- "source": [
- "Next, we create a Spatial DataFrame for our road features using the Overture transportation segment table."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "153238ce-9922-49bd-9868-75bbb787430a",
- "metadata": {},
- "outputs": [],
- "source": [
- "val roadsDf = sedona.table(\"wherobots_open_data.overture_2024_02_15.transportation_segment\")\n",
- " .select(\n",
- " col(\"geometry\"),\n",
- " lit(\"roads\").alias(\"layer\"),\n",
- " element_at(col(\"sources\"), 1)(\"dataset\").alias(\"source\")\n",
- " )\n",
- "\n",
- "roadsDf.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "89d88540",
- "metadata": {},
- "source": [
- "Next, we prepare a single spatial DataFrame combining our roads and buildings features."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "177c4d70-6fab-496b-8b3d-6bdfcd15df18",
- "metadata": {},
- "outputs": [],
- "source": [
- "var featuresDf = roadsDf.union(buildingsDf)\n",
- "\n",
- "featuresDf = if (filter) featuresDf.filter(filterExpression) else featuresDf\n",
- "\n",
- "featuresDf.count()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a2c7de7c-e705-45f1-829c-43114475e5d2",
- "metadata": {},
- "source": [
- "### Create Tiles as a PMTiles Archive\n",
- "\n",
- "Once we have the Spatial DataFrame ready for tile generation, we can use the `vtiles.generate_pmtiles` method to create a PMTiles archive. PMTiles is a performant, simple, and optimized format for storing vector tiles.\n",
- "\n",
- "Wherobots will automatically handle the details for you. However, if you need more control, a `GenerationConfig` object can optionally be provided as an argument to control which tiles are created and their contents. A `PMTilesConfig` object can optionally be provided to control the header information of the PMTiles Archive.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ee1a466c-f88b-41c0-b3e8-dd125c117a77",
- "metadata": {},
- "outputs": [],
- "source": [
- "import com.wherobots.VTiles\n",
- "\n",
- "val fullTilesPath = sys.env(\"USER_S3_PATH\") + \"tiles.pmtiles\"\n",
- "val tilesDf = VTiles.generatePMTiles(featuresDf, fullTilesPath)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "6d61fea1-ebd6-4b8b-a974-7a93d7c5de42",
- "metadata": {},
- "source": [
- "## Quick Generation of Tiles\n",
- "\n",
- "Sometimes you want to quickly visualize a massive dataset. To achieve this goal, WherobotsDB provides functionality for\n",
- "quickly generating and saving tiles. When testing this function it completed 100 million features in\n",
- "less than 5 minutes on a Wherobots Cloud Cairo runtime. This is accomplished by limiting the features processed to 100 million and\n",
- "generating fewer zoom levels at a higher resolution. At high zooms, the low precision from the low maximum zoom may be\n",
- "evident.\n",
- "\n",
- "The Scala/Java API exposes the `getQuickConfig` method which can be passed to\n",
- "the `vtiles.generate` or `vtiles.generatePMTiles` methods for the same tile generation functionality.\n",
- "\n",
- "This feature can be used as follows:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "23a7b83a-d52f-4a2f-8239-24b64350b8fd",
- "metadata": {},
- "outputs": [],
- "source": [
- "val SampleTilesPath = sys.env(\"USER_S3_PATH\") + \"sampleTiles.pmtiles\"\n",
- "VTiles.generatePMTiles(featuresDf, SampleTilesPath, VTiles.getQuickConfig)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0f8e7982-26e1-4faa-805e-d274c2af39d5",
- "metadata": {},
- "source": [
- "As a comprehensive map application toolbox, WherobotsDB provides many off-the-shelf scalable tools. In this\n",
- "tutorial, we just focus on a minimum example. Detailed explanation of each tool can be found\n",
- "in [the documentation](https://docs.wherobots.com/latest/references/wherobotsdb/vector-data/Overview/)."
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Scala",
- "language": "scala",
- "name": "spylon-kernel"
- },
- "language_info": {
- "codemirror_mode": "text/x-scala",
- "file_extension": ".scala",
- "help_links": [
- {
- "text": "MetaKernel Magics",
- "url": "https://metakernel.readthedocs.io/en/latest/source/README.html"
- }
- ],
- "mimetype": "text/x-scala",
- "name": "scala",
- "pygments_lexer": "scala",
- "version": "0.4.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/scala/wherobots-db/wherobots-db-example-scala.ipynb b/scala/wherobots-db/wherobots-db-example-scala.ipynb
deleted file mode 100644
index 6d47106..0000000
--- a/scala/wherobots-db/wherobots-db-example-scala.ipynb
+++ /dev/null
@@ -1,135 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "246055dd-6c4d-4a3c-8ed5-e4569c9c399d",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# WherobotsDB Example Notebook - Scala\n",
- "\n",
- "This notebook demonstrates loading Shapefile data, performing a spatial join operation and writing the results as GeoParquet. \n",
- "\n",
- "First, we import Python dependencies and then configure WherobotsDB to access the public `wherobots-examples` AWS S3 bucket using anonymous credentials. You can read more about configuring file access in the [documentation.](https://docs.wherobots.com/latest/references/havasu/configuration/cross-account/?h=s3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dddd6f1f-c6ad-4f48-82ae-46d4e8573b8f",
- "metadata": {},
- "outputs": [],
- "source": [
- "%%init_spark\n",
- "launcher.conf.set(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8f061462-8ca0-4a26-ac84-eab58da27e1f",
- "metadata": {},
- "outputs": [],
- "source": [
- "import org.apache.sedona.core.formatMapper.shapefileParser.ShapefileReader\n",
- "import org.apache.sedona.spark.SedonaContext\n",
- "import org.apache.sedona.sql.utils.Adapter\n",
- "import org.apache.spark.sql.SaveMode\n",
- "import org.apache.spark.sql.functions.desc"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d9a0ca5e-0c8c-4abc-9f5e-bb9143e14621",
- "metadata": {},
- "outputs": [],
- "source": [
- "val sedona = SedonaContext.create(spark)\n",
- "val sc = sedona.sparkContext"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c9534ce5-b7f1-45b9-bc80-f32b0d6bf468",
- "metadata": {},
- "outputs": [],
- "source": [
- "// Read the countries shapefiles from S3\n",
- "val s3BucketName = \"wherobots-examples\"\n",
- "val countries = ShapefileReader.readToGeometryRDD(sc, s\"s3://$s3BucketName/data/ne_50m_admin_0_countries_lakes/\")\n",
- "// Convert the Spatial RDD to a Spatial DataFrame using the Adapter\n",
- "val countries_df = Adapter.toDf(countries, sedona)\n",
- "countries_df.createOrReplaceTempView(\"country\")\n",
- "countries_df.printSchema()\n",
- "\n",
- "// countries_df.write.format(\"havasu.iceberg\").saveAsTable(\"my_catalog.test_db.country\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c2b47b60-b73f-4d94-8f11-16706afde242",
- "metadata": {},
- "outputs": [],
- "source": [
- "// Read the airports shapefiles from S3\n",
- "val airports = ShapefileReader.readToGeometryRDD(sc, s\"s3://$s3BucketName/data/ne_50m_airports/\")\n",
- "// Convert the Spatial RDD to a Spatial DataFrame using the Adapter\n",
- "val airports_df = Adapter.toDf(airports, sedona)\n",
- "airports_df.createOrReplaceTempView(\"airport\")\n",
- "airports_df.printSchema()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f6634c32-0a8b-414b-9d14-c50ccfbfd10a",
- "metadata": {},
- "outputs": [],
- "source": [
- "// Run a spatial join query to find airports in each country\n",
- "val result = sedona.sql(\"SELECT c.geometry as country_geom, c.NAME_EN, a.geometry as airport_geom, a.name FROM country c, airport a WHERE ST_Contains(c.geometry, a.geometry)\")\n",
- "// Aggregate the results to find the number of airports in each country\n",
- "val aggregateResult = result.groupBy(\"NAME_EN\", \"country_geom\").count()\n",
- "aggregateResult.orderBy(desc(\"count\")).show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d4dd5a05-91bc-4df7-9b47-25b684089cfd",
- "metadata": {},
- "outputs": [],
- "source": [
- "// Write the results to a GeoParquet file\n",
- "aggregateResult.write.format(\"geoparquet\").mode(SaveMode.Overwrite).save(sys.env(\"USER_S3_PATH\") + \"airport_country.parquet\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Scala",
- "language": "scala",
- "name": "spylon-kernel"
- },
- "language_info": {
- "codemirror_mode": "text/x-scala",
- "file_extension": ".scala",
- "help_links": [
- {
- "text": "MetaKernel Magics",
- "url": "https://metakernel.readthedocs.io/en/latest/source/README.html"
- }
- ],
- "mimetype": "text/x-scala",
- "name": "scala",
- "pygments_lexer": "scala",
- "version": "0.4.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/snippets/1-1-Loading-Geospatial-Data.ipynb b/snippets/1-1-Loading-Geospatial-Data.ipynb
new file mode 100644
index 0000000..541e345
--- /dev/null
+++ b/snippets/1-1-Loading-Geospatial-Data.ipynb
@@ -0,0 +1,606 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "f68625d5-96ed-4760-b256-cf8320d0df6e",
+ "metadata": {},
+ "source": [
+ "# Loading Geospatial Data with Wherobots\n",
+ "\n",
+ "## 📖 Introduction\n",
+ "In this notebook, we will demonstrate how to load geospatial data into Wherobots using the following formats:\n",
+ "\n",
+ "1. **GeoParquet**\n",
+ "2. **GeoJSON and Shapefiles**\n",
+ "3. **Raster Data (GeoTIFF)**\n",
+ "4. **Overture Maps Data**\n",
+ "5. **Data from S3**\n",
+ "\n",
+ "Each section will walk through the necessary steps with annotated code and provide links to relevant Wherobots documentation.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "86231554-78ee-48af-b15d-8f8af35b5cbc",
+ "metadata": {},
+ "source": [
+ "## 🗂 Step 1: Loading GeoParquet Files\n",
+ "\n",
+ "### What you'll learn:\n",
+ "- How to load GeoParquet files into a DataFrame.\n",
+ "- Perform basic spatial queries."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "id": "4b8a35c2-7767-489a-b0b2-c1f21c31d965",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:21:07.789305Z",
+ "iopub.status.busy": "2025-03-07T16:21:07.789105Z",
+ "iopub.status.idle": "2025-03-07T16:21:07.792386Z",
+ "shell.execute_reply": "2025-03-07T16:21:07.792059Z",
+ "shell.execute_reply.started": "2025-03-07T16:21:07.789291Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Import necessary libraries\n",
+ "from sedona.sql.st_predicates import ST_Intersects\n",
+ "from sedona.sql.st_constructors import ST_GeomFromText\n",
+ "from sedona.spark import SedonaContext\n",
+ "from pyspark.sql import SparkSession"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "a56cc531-a04b-450c-b390-60b00fc4018b",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:17.238247Z",
+ "iopub.status.busy": "2025-03-07T16:09:17.238032Z",
+ "iopub.status.idle": "2025-03-07T16:09:41.182469Z",
+ "shell.execute_reply": "2025-03-07T16:09:41.181646Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:17.238231Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Setting default log level to \"WARN\".\n",
+ "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n",
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# Initialize Sedona and Spark session\n",
+ "config = SparkSession.builder \\\n",
+ " .appName(\"Dataset Loader\") \\\n",
+ " .getOrCreate()\n",
+ "sedona = SedonaContext.create(config)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "f1d98faa-6334-4f1e-b61a-f6fbb95e04ed",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:41.185538Z",
+ "iopub.status.busy": "2025-03-07T16:09:41.185380Z",
+ "iopub.status.idle": "2025-03-07T16:09:43.441805Z",
+ "shell.execute_reply": "2025-03-07T16:09:43.441239Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:41.185522Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# Load GeoParquet data\n",
+ "gdf = sedona.read.format(\"geoparquet\").load(\"s3://wherobots-examples/data/mini/es_cn.parquet\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d00e53f4-1f98-4b2c-9565-48ae49510f7a",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:43.443049Z",
+ "iopub.status.busy": "2025-03-07T16:09:43.442903Z",
+ "iopub.status.idle": "2025-03-07T16:09:43.447953Z",
+ "shell.execute_reply": "2025-03-07T16:09:43.447443Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:43.443034Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "root\n",
+ " |-- id: string (nullable = true)\n",
+ " |-- geometry: geometry (nullable = true)\n",
+ " |-- determination_datetime: timestamp (nullable = true)\n",
+ " |-- admin_island: string (nullable = true)\n",
+ " |-- crop:code: string (nullable = true)\n",
+ " |-- crop:name: string (nullable = true)\n",
+ " |-- area: float (nullable = true)\n",
+ " |-- admin:country_code: string (nullable = true)\n",
+ " |-- admin:subdivision_code: string (nullable = true)\n",
+ " |-- crop:code_list: string (nullable = true)\n",
+ " |-- bbox: struct (nullable = true)\n",
+ " | |-- xmin: double (nullable = true)\n",
+ " | |-- ymin: double (nullable = true)\n",
+ " | |-- xmax: double (nullable = true)\n",
+ " | |-- ymax: double (nullable = true)\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "gdf.printSchema()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fef54f08-3606-483e-8639-e9443c524e29",
+ "metadata": {},
+ "source": [
+ "📄 **Documentation Reference**: [Loading GeoParquet](https://docs.wherobots.com/#geoparquet-loading) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8ca72a65-a152-4598-99eb-1702b48481f6",
+ "metadata": {},
+ "source": [
+ "## 🌍 Step 2: Loading GeoJSON and Shapefiles\n",
+ "\n",
+ "### What you'll learn:\n",
+ "- How to ingest GeoJSON and Shapefiles."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "267c1d53-b6d6-444e-a8e2-bafcad689e35",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:43.448990Z",
+ "iopub.status.busy": "2025-03-07T16:09:43.448625Z",
+ "iopub.status.idle": "2025-03-07T16:09:52.317628Z",
+ "shell.execute_reply": "2025-03-07T16:09:52.316976Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:43.448970Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# Load GeoJSON file\n",
+ "geojson_df = sedona.read.format(\"geojson\").load(\"s3://wherobots-examples/data/mini/2015_Tree_Census.geojson\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "ac227690-0694-4575-a151-5a28b7f9ccb7",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:52.318493Z",
+ "iopub.status.busy": "2025-03-07T16:09:52.318307Z",
+ "iopub.status.idle": "2025-03-07T16:09:52.323283Z",
+ "shell.execute_reply": "2025-03-07T16:09:52.322792Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:52.318479Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "root\n",
+ " |-- _corrupt_record: string (nullable = true)\n",
+ " |-- geometry: geometry (nullable = true)\n",
+ " |-- properties: struct (nullable = true)\n",
+ " | |-- address: string (nullable = true)\n",
+ " | |-- block_id: string (nullable = true)\n",
+ " | |-- boro_ct: string (nullable = true)\n",
+ " | |-- borocode: string (nullable = true)\n",
+ " | |-- boroname: string (nullable = true)\n",
+ " | |-- brnch_ligh: string (nullable = true)\n",
+ " | |-- brnch_othe: string (nullable = true)\n",
+ " | |-- brnch_shoe: string (nullable = true)\n",
+ " | |-- cb_num: string (nullable = true)\n",
+ " | |-- cncldist: string (nullable = true)\n",
+ " | |-- created_at: string (nullable = true)\n",
+ " | |-- curb_loc: string (nullable = true)\n",
+ " | |-- guards: string (nullable = true)\n",
+ " | |-- health: string (nullable = true)\n",
+ " | |-- latitude: string (nullable = true)\n",
+ " | |-- longitude: string (nullable = true)\n",
+ " | |-- nta: string (nullable = true)\n",
+ " | |-- nta_name: string (nullable = true)\n",
+ " | |-- problems: string (nullable = true)\n",
+ " | |-- root_grate: string (nullable = true)\n",
+ " | |-- root_other: string (nullable = true)\n",
+ " | |-- root_stone: string (nullable = true)\n",
+ " | |-- sidewalk: string (nullable = true)\n",
+ " | |-- spc_common: string (nullable = true)\n",
+ " | |-- spc_latin: string (nullable = true)\n",
+ " | |-- st_assem: string (nullable = true)\n",
+ " | |-- st_senate: string (nullable = true)\n",
+ " | |-- state: string (nullable = true)\n",
+ " | |-- status: string (nullable = true)\n",
+ " | |-- steward: string (nullable = true)\n",
+ " | |-- stump_diam: string (nullable = true)\n",
+ " | |-- tree_dbh: string (nullable = true)\n",
+ " | |-- tree_id: string (nullable = true)\n",
+ " | |-- trnk_light: string (nullable = true)\n",
+ " | |-- trnk_other: string (nullable = true)\n",
+ " | |-- trnk_wire: string (nullable = true)\n",
+ " | |-- user_type: string (nullable = true)\n",
+ " | |-- x_sp: string (nullable = true)\n",
+ " | |-- y_sp: string (nullable = true)\n",
+ " | |-- zip_city: string (nullable = true)\n",
+ " | |-- zipcode: string (nullable = true)\n",
+ " |-- type: string (nullable = true)\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "geojson_df.printSchema()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "24cacf97-3517-4e6b-9120-72199803c98f",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:09:52.324047Z",
+ "iopub.status.busy": "2025-03-07T16:09:52.323881Z",
+ "iopub.status.idle": "2025-03-07T16:10:00.329160Z",
+ "shell.execute_reply": "2025-03-07T16:10:00.328810Z",
+ "shell.execute_reply.started": "2025-03-07T16:09:52.324034Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "[Stage 5:====================================================> (11 + 1) / 12]\r"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "root\n",
+ " |-- _corrupt_record: string (nullable = true)\n",
+ " |-- geometry: geometry (nullable = true)\n",
+ " |-- address: string (nullable = true)\n",
+ " |-- spc_common: string (nullable = true)\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "import pyspark.sql.functions as f\n",
+ "\n",
+ "df = sedona.read.format(\"geojson\").load(\"s3://wherobots-examples/data/mini/2015_Tree_Census.geojson\") \\\n",
+ " .withColumn(\"address\", f.expr(\"properties['address']\")) \\\n",
+ " .withColumn(\"spc_common\", f.expr(\"properties['spc_common']\")) \\\n",
+ " .drop(\"properties\").drop(\"type\")\n",
+ "\n",
+ "df.printSchema()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "59ed79b6-76dd-4045-a7f0-d6b258d01a00",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:10:00.329891Z",
+ "iopub.status.busy": "2025-03-07T16:10:00.329725Z",
+ "iopub.status.idle": "2025-03-07T16:10:00.810961Z",
+ "shell.execute_reply": "2025-03-07T16:10:00.810562Z",
+ "shell.execute_reply.started": "2025-03-07T16:10:00.329876Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Load Shapefile\n",
+ "shapefile_df = sedona.read.format(\"shapefile\").load(\"s3://wherobots-examples/data/mini/HurricaneSandy/geo_export_2ca210ed-d8b2-4fe6-81eb-53cc96311073.shp\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "59728efd-638a-4449-9d46-5f1239fcb786",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:10:00.811945Z",
+ "iopub.status.busy": "2025-03-07T16:10:00.811656Z",
+ "iopub.status.idle": "2025-03-07T16:10:00.816066Z",
+ "shell.execute_reply": "2025-03-07T16:10:00.815656Z",
+ "shell.execute_reply.started": "2025-03-07T16:10:00.811925Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "root\n",
+ " |-- geometry: geometry (nullable = true)\n",
+ " |-- comments: string (nullable = true)\n",
+ " |-- state: string (nullable = true)\n",
+ " |-- demsource: string (nullable = true)\n",
+ " |-- id: decimal(33,31) (nullable = true)\n",
+ " |-- status: string (nullable = true)\n",
+ " |-- sourcedata: string (nullable = true)\n",
+ " |-- verified: string (nullable = true)\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Inspect and perform a query\n",
+ "shapefile_df.printSchema()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "94031647-3ad1-4d94-b5ba-31dbded9cc98",
+ "metadata": {},
+ "source": [
+ "📄 **Documentation Reference**: [Ingesting GeoJSON](https://docs.wherobots.com/#geojson-loading) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7bd8ec2c-92a0-4989-8c0c-79eb1e9003ce",
+ "metadata": {},
+ "source": [
+ "## 🖼️ Step 3: Loading Raster Data (GeoTIFF)\n",
+ "\n",
+ "### What you'll learn:\n",
+ "- How to load raster datasets and inspect metadata.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "0867b6ba-bc70-4737-801d-672cda6d2de1",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:10:00.816818Z",
+ "iopub.status.busy": "2025-03-07T16:10:00.816643Z",
+ "iopub.status.idle": "2025-03-07T16:10:00.952233Z",
+ "shell.execute_reply": "2025-03-07T16:10:00.951744Z",
+ "shell.execute_reply.started": "2025-03-07T16:10:00.816801Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Load a GeoTIFF raster file\n",
+ "raster_df = sedona.read.format(\"binaryFile\").load(\"s3://wherobots-examples/data/mini/NYC_3ft_Landcover.tif\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "012e882b-08ec-4851-9f91-4d0034bdae08",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:10:00.953661Z",
+ "iopub.status.busy": "2025-03-07T16:10:00.953430Z",
+ "iopub.status.idle": "2025-03-07T16:10:01.028255Z",
+ "shell.execute_reply": "2025-03-07T16:10:01.027685Z",
+ "shell.execute_reply.started": "2025-03-07T16:10:00.953648Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Convert binary content to a raster object\n",
+ "raster_df = raster_df.selectExpr(\"RS_FromGeoTiff(content) as raster\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "90591236-c0f1-4363-b7f0-d02ed91ad442",
+ "metadata": {},
+ "source": [
+ "📄 **Documentation Reference**: [Loading Raster Data](https://docs.wherobots.com/#raster-loading) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ef3be7bd-dc6f-4223-9658-80713ef7c33e",
+ "metadata": {},
+ "source": [
+ "## 🗺️ Step 4: Loading Overture Maps Data\n",
+ "\n",
+ "### What you'll learn:\n",
+ "- Load and query datasets provided by Overture Maps.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "434911d2-de1a-4936-9045-31ddc74808bd",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:13:28.948088Z",
+ "iopub.status.busy": "2025-03-07T16:13:28.947862Z",
+ "iopub.status.idle": "2025-03-07T16:13:30.502992Z",
+ "shell.execute_reply": "2025-03-07T16:13:30.502603Z",
+ "shell.execute_reply.started": "2025-03-07T16:13:28.948074Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Load Overture Maps building dataset\n",
+ "buildings_df = sedona.read.format(\"iceberg\").load(\"wherobots_open_data.overture.buildings_building\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "id": "424f9a3c-f7d4-4202-b678-f65303c455a0",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:21:47.122170Z",
+ "iopub.status.busy": "2025-03-07T16:21:47.121961Z",
+ "iopub.status.idle": "2025-03-07T16:21:47.136445Z",
+ "shell.execute_reply": "2025-03-07T16:21:47.135843Z",
+ "shell.execute_reply.started": "2025-03-07T16:21:47.122155Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Filter based on geometry (example: within a bounding box)\n",
+ "bbox_wkt = '''POLYGON((-122.5 37.0, -122.5 37.5, -121.5 37.5, -121.5 37.0, -122.5 37.0))'''\n",
+ "buildings_filtered = buildings_df.where(ST_Intersects(\"geometry\", f.expr(f'''ST_GeomFromText('{bbox_wkt}')''')))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "id": "a74b4e22-6e42-4a2f-b792-6d86c6b50f66",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-07T16:21:48.224977Z",
+ "iopub.status.busy": "2025-03-07T16:21:48.224762Z",
+ "iopub.status.idle": "2025-03-07T16:21:51.624700Z",
+ "shell.execute_reply": "2025-03-07T16:21:51.624045Z",
+ "shell.execute_reply.started": "2025-03-07T16:21:48.224962Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "[Stage 8:> (0 + 1) / 1]\r"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+--------------------+--------------------+-------+-----+-----+------+---------+-----------+--------------------+--------------------+--------------------+-------+\n",
+ "| id| updatetime|version|names|level|height|numfloors| class| sources| bbox| geometry|geohash|\n",
+ "+--------------------+--------------------+-------+-----+-----+------+---------+-----------+--------------------+--------------------+--------------------+-------+\n",
+ "|tmp_7733393231353...|2016-01-18T20:36:...| 0| {}| NULL| 2.4| NULL| NULL|[{dataset -> USGS...|{-122.1369756, -1...|POLYGON ((-122.13...| 9q|\n",
+ "|tmp_7731303530363...|2022-04-10T04:52:...| 0| {}| NULL| NULL| NULL|residential|[{dataset -> Open...|{-122.1396009, -1...|POLYGON ((-122.13...| 9q|\n",
+ "|tmp_7733373936373...|2021-10-02T19:44:...| 0| {}| NULL| 3.6| NULL| NULL|[{dataset -> Open...|{-121.8066009, -1...|POLYGON ((-121.80...| 9q|\n",
+ "|tmp_7733383238373...|2015-11-26T15:12:...| 0| {}| NULL| NULL| NULL| NULL|[{dataset -> Open...|{-122.2115413, -1...|POLYGON ((-122.21...| 9q|\n",
+ "|tmp_7733393032363...|2016-01-08T18:03:...| 0| {}| NULL| 4.0| NULL| NULL|[{dataset -> USGS...|{-122.0189285, -1...|POLYGON ((-122.01...| 9q|\n",
+ "|tmp_7733353937303...|2021-10-02T19:44:...| 0| {}| NULL| 4.1| NULL| NULL|[{dataset -> Open...|{-121.8013576, -1...|POLYGON ((-121.80...| 9q|\n",
+ "|tmp_7733343038343...|2015-04-27T08:16:...| 0| {}| NULL| 4.1| NULL| NULL|[{dataset -> USGS...|{-121.549742, -12...|POLYGON ((-121.54...| 9q|\n",
+ "|tmp_7733363238313...|2022-06-12T04:43:...| 0| {}| NULL| 6.41| NULL|residential|[{dataset -> Open...|{-121.8049453, -1...|POLYGON ((-121.80...| 9q|\n",
+ "|tmp_7739353431303...|2021-06-14T01:00:...| 0| {}| NULL| 2.65| NULL| NULL|[{dataset -> Open...|{-121.8103125, -1...|POLYGON ((-121.81...| 9q|\n",
+ "|tmp_7732353634343...|2020-10-30T02:13:...| 0| {}| NULL| 4.4| 1|residential|[{dataset -> USGS...|{-122.0558462, -1...|POLYGON ((-122.05...| 9q|\n",
+ "|tmp_7739303639353...|2021-02-14T02:20:...| 0| {}| NULL| 4.92| NULL| NULL|[{dataset -> Open...|{-121.9062614, -1...|POLYGON ((-121.90...| 9q|\n",
+ "|tmp_3538303432313...|2023-07-01T07:00:...| 0| {}| NULL| 7.8| NULL| NULL|[{dataset -> USGS...|{-122.0043632, -1...|POLYGON ((-122.00...| 9q|\n",
+ "|tmp_7738303437393...|2020-05-17T02:55:...| 0| {}| NULL| 3.89| NULL| NULL|[{dataset -> Open...|{-122.0269517, -1...|POLYGON ((-122.02...| 9q|\n",
+ "|tmp_7739313930313...|2021-03-19T04:25:...| 0| {}| NULL| 3.36| NULL| NULL|[{dataset -> Open...|{-121.8794212, -1...|POLYGON ((-121.87...| 9q|\n",
+ "|tmp_7738333433373...|2020-08-06T01:23:...| 0| {}| NULL| 4.29| NULL| NULL|[{dataset -> Open...|{-121.9918305, -1...|POLYGON ((-121.99...| 9q|\n",
+ "|tmp_7732333932353...|2013-09-25T17:31:...| 0| {}| NULL| NULL| NULL| NULL|[{dataset -> Open...|{-122.1968669, -1...|POLYGON ((-122.19...| 9q|\n",
+ "|tmp_7733383238393...|2015-11-26T17:07:...| 0| {}| NULL| 7.2| NULL| NULL|[{dataset -> USGS...|{-122.1817277, -1...|POLYGON ((-122.18...| 9q|\n",
+ "|tmp_7733393134303...|2016-01-14T16:17:...| 0| {}| NULL| 5.0| NULL| NULL|[{dataset -> USGS...|{-121.9938749, -1...|POLYGON ((-121.99...| 9q|\n",
+ "|tmp_3537383835303...|2023-07-01T07:00:...| 0| {}| NULL| NULL| NULL| NULL|[{dataset -> Micr...|{-122.1612029, -1...|POLYGON ((-122.16...| 9q|\n",
+ "|tmp_3538333836373...|2023-07-01T07:00:...| 0| {}| NULL| 2.5| NULL| NULL|[{dataset -> USGS...|{-121.659981, -12...|POLYGON ((-121.65...| 9q|\n",
+ "+--------------------+--------------------+-------+-----+-----+------+---------+-----------+--------------------+--------------------+--------------------+-------+\n",
+ "only showing top 20 rows\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# Show results\n",
+ "buildings_filtered.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e38e86b3-30bb-4a39-9954-90e002d3737b",
+ "metadata": {},
+ "source": [
+ "## 🔮 Next Steps\n",
+ "\n",
+ "In this notebook, we demonstrated how to:\n",
+ "\n",
+ "1. Load GeoParquet, GeoJSON, Shapefiles, and raster data into Wherobots.\n",
+ "2. Query spatial data using basic spatial operations.\n",
+ "3. Integrate datasets directly from S3 and Overture Maps.\n",
+ "\n",
+ "### What’s next?\n",
+ "- Explore **spatial transformations** like buffering or intersecting geometries.\n",
+ "- Perform **spatial joins** for more advanced analytics.\n",
+ "- Visualize query results with **SedonaKepler** or **SedonaPyDeck**.\n",
+ "\n",
+ "For further details, check out the [Wherobots Documentation](https://docs.wherobots.com).\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.11.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/python/wherobots-ai/conf/map_config.json b/wherobots-ai/conf/map_config.json
similarity index 100%
rename from python/wherobots-ai/conf/map_config.json
rename to wherobots-ai/conf/map_config.json
diff --git a/python/wherobots-ai/dbscan_example.ipynb b/wherobots-ai/dbscan_example.ipynb
similarity index 100%
rename from python/wherobots-ai/dbscan_example.ipynb
rename to wherobots-ai/dbscan_example.ipynb
diff --git a/python/wherobots-ai/glocal_example.ipynb b/wherobots-ai/glocal_example.ipynb
similarity index 100%
rename from python/wherobots-ai/glocal_example.ipynb
rename to wherobots-ai/glocal_example.ipynb
diff --git a/python/wherobots-ai/gpu/bring_your_own_model_tutorial.ipynb b/wherobots-ai/gpu/bring_your_own_model_tutorial.ipynb
similarity index 100%
rename from python/wherobots-ai/gpu/bring_your_own_model_tutorial.ipynb
rename to wherobots-ai/gpu/bring_your_own_model_tutorial.ipynb
diff --git a/python/wherobots-ai/gpu/classification.ipynb b/wherobots-ai/gpu/classification.ipynb
similarity index 100%
rename from python/wherobots-ai/gpu/classification.ipynb
rename to wherobots-ai/gpu/classification.ipynb
diff --git a/python/wherobots-ai/gpu/img/asset-form.png b/wherobots-ai/gpu/img/asset-form.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/asset-form.png
rename to wherobots-ai/gpu/img/asset-form.png
diff --git a/python/wherobots-ai/gpu/img/byom-model-pt.png b/wherobots-ai/gpu/img/byom-model-pt.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/byom-model-pt.png
rename to wherobots-ai/gpu/img/byom-model-pt.png
diff --git a/python/wherobots-ai/gpu/img/byom-storage-copy.png b/wherobots-ai/gpu/img/byom-storage-copy.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/byom-storage-copy.png
rename to wherobots-ai/gpu/img/byom-storage-copy.png
diff --git a/python/wherobots-ai/gpu/img/byom-storage.png b/wherobots-ai/gpu/img/byom-storage.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/byom-storage.png
rename to wherobots-ai/gpu/img/byom-storage.png
diff --git a/python/wherobots-ai/gpu/img/classification.png b/wherobots-ai/gpu/img/classification.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/classification.png
rename to wherobots-ai/gpu/img/classification.png
diff --git a/python/wherobots-ai/gpu/img/mlm-form.png b/wherobots-ai/gpu/img/mlm-form.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/mlm-form.png
rename to wherobots-ai/gpu/img/mlm-form.png
diff --git a/python/wherobots-ai/gpu/img/object-detection.png b/wherobots-ai/gpu/img/object-detection.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/object-detection.png
rename to wherobots-ai/gpu/img/object-detection.png
diff --git a/python/wherobots-ai/gpu/img/offshore_oil.png b/wherobots-ai/gpu/img/offshore_oil.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/offshore_oil.png
rename to wherobots-ai/gpu/img/offshore_oil.png
diff --git a/python/wherobots-ai/gpu/img/satelite.png b/wherobots-ai/gpu/img/satelite.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/satelite.png
rename to wherobots-ai/gpu/img/satelite.png
diff --git a/python/wherobots-ai/gpu/img/segmentation.png b/wherobots-ai/gpu/img/segmentation.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/segmentation.png
rename to wherobots-ai/gpu/img/segmentation.png
diff --git a/python/wherobots-ai/gpu/img/wind_farm.png b/wherobots-ai/gpu/img/wind_farm.png
similarity index 100%
rename from python/wherobots-ai/gpu/img/wind_farm.png
rename to wherobots-ai/gpu/img/wind_farm.png
diff --git a/python/wherobots-ai/gpu/object_detection.ipynb b/wherobots-ai/gpu/object_detection.ipynb
similarity index 100%
rename from python/wherobots-ai/gpu/object_detection.ipynb
rename to wherobots-ai/gpu/object_detection.ipynb
diff --git a/python/wherobots-ai/gpu/segmentation.ipynb b/wherobots-ai/gpu/segmentation.ipynb
similarity index 100%
rename from python/wherobots-ai/gpu/segmentation.ipynb
rename to wherobots-ai/gpu/segmentation.ipynb
diff --git a/python/wherobots-ai/lof_example.ipynb b/wherobots-ai/lof_example.ipynb
similarity index 100%
rename from python/wherobots-ai/lof_example.ipynb
rename to wherobots-ai/lof_example.ipynb
diff --git a/python/wherobots-ai/mapmatching_example.ipynb b/wherobots-ai/mapmatching_example.ipynb
similarity index 100%
rename from python/wherobots-ai/mapmatching_example.ipynb
rename to wherobots-ai/mapmatching_example.ipynb
diff --git "a/\342\236\241\357\270\217-START-HERE-Onboarding-Part-1.ipynb" "b/\342\236\241\357\270\217-START-HERE-Onboarding-Part-1.ipynb"
new file mode 100644
index 0000000..e244c96
--- /dev/null
+++ "b/\342\236\241\357\270\217-START-HERE-Onboarding-Part-1.ipynb"
@@ -0,0 +1,791 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "47fdb871-c5a8-4588-8a22-aad4207e058d",
+ "metadata": {},
+ "source": [
+ "# 🎉 Welcome to Wherobots! 🚀\n",
+ "\n",
+ "We are *thrilled* to have you here and can't wait to help you get started! Before diving in, take a moment to watch this video below:\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0892b7ec-6452-4797-90bc-a2934bd201ad",
+ "metadata": {},
+ "source": [
+ "## 🌍 What You Will Learn in This Notebook\n",
+ "\n",
+ "Welcome to this geospatial analysis notebook! By the end of this notebook, you will have learned how to:\n",
+ "\n",
+ "### 1. **📂 Load raster and vector files into Dataframes**\n",
+ "- Load in geospatial data into Sedona Dataframes from data on AWS S3.\n",
+ "- Use Apache Sedona SQL to filter, query, and manipulate vector and raster data.\n",
+ "\n",
+ "### 2. **📊 Perform Zonal Statistics**\n",
+ "- Leverage `RS_ZonalStats` to calculate statistics like mean temperature over spatial geometries.\n",
+ "- Integrate raster and vector data for advanced spatial analysis.\n",
+ "\n",
+ "### 3. **🔄 Transform and Analyze Data**\n",
+ "- Use SQL queries to extract insights, such as identifying regions meeting specific criteria (e.g. building elevation).\n",
+ "\n",
+ "### 4. **📝 Work with Temporary Views**\n",
+ "- Understand the use of temporary views in Apache Sedona to streamline complex geospatial workflows.\n",
+ "\n",
+ "### 5. **🗺️ Visualize and Interpret Results**\n",
+ "- Learn how to visualize geospatial datasets using tools like SedonaKepler.\n",
+ "- Explore insights derived from the data, such as building heights.\n",
+ "\n",
+ "This notebook emphasizes hands-on geospatial analysis, combining the power of SQL, Python, and cloud-native data integration to unlock actionable insights from spatial datasets.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "677df1c0-8c78-4fac-a3a8-59203a9ce0f5",
+ "metadata": {
+ "jp-MarkdownHeadingCollapsed": true
+ },
+ "source": [
+ "# Step 1: **Choose Your Storage**\n",
+ "\n",
+ "Wherobots is a **cloud-native tool** and works best with data stored in a cloud storage bucket. You have two options:\n",
+ "\n",
+ "1. **Use Wherobots S3 storage** (our fully managed solution).\n",
+ "2. **Connect your own S3 buckets** to integrate seamlessly with your existing data workflows.\n",
+ "\n",
+ "> *Tip*: Storing data in the cloud makes it easier to scale, process, and analyze geospatial data efficiently! 🌩️\n",
+ "\n",
+ "Don't worry you don't need to make that decision to move ahead with this tutorial! **We have some data ready to use**!\n",
+ "\n",
+ "If you want to use **Wherobots Managed Storage** [click here to get some more information](https://docs.wherobots.com/latest/develop/storage-management/managed-storage/) about how to load your data in."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "206a529d-9936-4edc-82d8-a34553c61f92",
+ "metadata": {},
+ "source": [
+ "# Step 2: **Set up your Sedona context**\n",
+ "\n",
+ "This is the machine that makes everything run. It will connect you to Wherobots Cloud compute environment to make sure everything runs 🏎️ **fast and efficiently**.\n",
+ "\n",
+ "#### 🧰 **The configuration**\n",
+ "This first step allows you to set up the configuration for your compute environment. There are other things you can add into this if you want but this is the base to get you up and running.\n",
+ "\n",
+ "```python\n",
+ "config = SedonaContext.builder().getOrCreate()\n",
+ "```\n",
+ "\n",
+ "#### 🔌 **The context**\n",
+ "And this code will connect your new configuration to the Wherobots Cloud compute environment that you started up.\n",
+ "\n",
+ "```python\n",
+ "sedona = SedonaContext.create(config)\n",
+ "```\n",
+ "\n",
+ "> 📓 Here is some more [information from our documentation](https://docs.wherobots.com/latest/develop/notebook-management/notebook-instance-management/) on setting up your compute environment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "43735554-a11f-40b5-ae9b-b165121b7b06",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Setting default log level to \"WARN\".\n",
+ "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n",
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "from sedona.spark import SedonaContext\n",
+ "\n",
+ "config = SedonaContext.builder().getOrCreate()\n",
+ "sedona = SedonaContext.create(config)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4043b66a-0013-4026-b4b5-3ffbe4734d5c",
+ "metadata": {},
+ "source": [
+ "# Step 3: **Load a GeoParquet File Into a DataFrame**\n",
+ "\n",
+ "GeoParquet is a modern, efficient format for storing geospatial data. Here's how to load a GeoParquet file into a DataFrame:\n",
+ "\n",
+ "#### 📂 **Load the GeoParquet File**\n",
+ "Use the following code snippet to load a GeoParquet file from S3 - you don't need any extra libraries to do so!:\n",
+ "\n",
+ "```python\n",
+ "# Load the dataframe using your S3 URL\n",
+ "df = sedona.read.format(\"geoparquet\").load(geoparquetdatalocation1)\n",
+ "\n",
+ "# First show the data schema using the .printSchema() function\n",
+ "df.printSchema()\n",
+ "\n",
+ "# Then show the first 20 rows of the dataframe\n",
+ "df.show()\n",
+ "\n",
+ "# ...or the first 5 rows\n",
+ "df.show(5)\n",
+ "```\n",
+ "\n",
+ "> *Note*: GeoParquet files store geospatial data in an efficient, interoperable format. This makes them perfect for large-scale geospatial workflows! 🌍 Here is some [more information from our documentation on loading GeoParquet](https://docs.wherobots.com/latest/tutorials/wherobotsdb/vector-data/vector-load/?h=read+geopar#__tabbed_9_3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "91712fe8-253d-4f10-b37d-777fdb3417fe",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:03:25.851073Z",
+ "iopub.status.busy": "2025-03-06T06:03:25.850727Z",
+ "iopub.status.idle": "2025-03-06T06:03:27.974311Z",
+ "shell.execute_reply": "2025-03-06T06:03:27.973712Z",
+ "shell.execute_reply.started": "2025-03-06T06:03:25.851041Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# Here we define a variable with the URI to our data in the S3 bucket\n",
+ "geoparquet = 's3://wherobots-examples/data/onboarding_1/nyc_buildings.parquet'\n",
+ "\n",
+ "# Then we can load that into a Sedona DataFrame \n",
+ "buildings = sedona.read.format(\"geoparquet\").load(geoparquet)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5e4d6708-cc64-4924-bdbb-32be45623c1d",
+ "metadata": {},
+ "source": [
+ "# Step 4: 📂 **Load in Raster Data Into a DataFrame**\n",
+ "Use the following code snippet to load a raster file (e.g., GeoTIFF) into a Sedona DataFrame:\n",
+ "\n",
+ "```python\n",
+ "# Define the path to your raster file\n",
+ "raster_path = \"s3://your-bucket-name/path/to/your/raster.tif\"\n",
+ "\n",
+ "# Load the raster file into a DataFrame using spatial SQL\n",
+ "elevation = sedona.sql(f'''SELECT RS_FromPath('{raster_path}') as rast''')\n",
+ "\n",
+ "# Show the schema and some sample rows\n",
+ "raster_df.printSchema()\n",
+ "raster_df.show()\n",
+ "\n",
+ "# Or load it using the Python API\n",
+ "df = sedona.read.format(\"raster\"). \\\n",
+ " load(raster_path)\n",
+ "```\n",
+ "\n",
+ "> *Note*: Make sure to adjust the `raster_path` to point to your specific file location. Sedona handles raster metadata and pixel data efficiently, making it ideal for spatial analysis. 🌐\n",
+ "\n",
+ "---\n",
+ "\n",
+ "### 🛠️ Next Steps\n",
+ "\n",
+ "- Use Sedona SQL to query and process your raster data.\n",
+ "- Combine raster and vector data for advanced spatial analytics.\n",
+ "\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "b05f28ac-c98a-4188-ae26-d36c2eed50ab",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:18:51.690976Z",
+ "iopub.status.busy": "2025-03-06T06:18:51.690737Z",
+ "iopub.status.idle": "2025-03-06T06:18:51.782959Z",
+ "shell.execute_reply": "2025-03-06T06:18:51.782182Z",
+ "shell.execute_reply.started": "2025-03-06T06:18:51.690962Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Once again we can define our S3 URI to our Raster dataset\n",
+ "central_park = 's3://wherobots-examples/data/onboarding_1/CentralPark.tif'\n",
+ "\n",
+ "# Here we can use the Sedona Spatial SQL functions to load the data in using the RS_FromPath function \n",
+ "elevation =sedona.read\\\n",
+ " .format(\"raster\")\\\n",
+ " .option(\"tileWidth\", \"256\")\\\n",
+ " .option(\"tileHeight\", \"256\")\\\n",
+ " .load(central_park)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "31c42f1e-bab2-4467-928b-fd80c75a6ae9",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:15:52.094017Z",
+ "iopub.status.busy": "2025-03-06T06:15:52.093826Z",
+ "iopub.status.idle": "2025-03-06T06:15:52.099117Z",
+ "shell.execute_reply": "2025-03-06T06:15:52.098438Z",
+ "shell.execute_reply.started": "2025-03-06T06:15:52.094003Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "root\n",
+ " |-- rast: raster (nullable = true)\n",
+ " |-- x: integer (nullable = true)\n",
+ " |-- y: integer (nullable = true)\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "elevation.printSchema()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "763f24d1-f824-4d57-a727-6ca55f785e10",
+ "metadata": {},
+ "source": [
+ "### **What is `elevation.createOrReplaceTempView('elevation')`?**\n",
+ "\n",
+ "This line of code is used to register a DataFrame as a temporary SQL view in Apache Spark. Here's what it does:\n",
+ "\n",
+ "- **`createOrReplaceTempView()`**: This method registers the DataFrame (in this case, `elevation`) as a temporary view.\n",
+ "- **`'elevation'`**: The name assigned to the SQL view. You can query this view using SQL commands in Spark SQL.\n",
+ "\n",
+ "#### 🛠️ Why Use a Temporary View?\n",
+ "\n",
+ "Temporary views allow you to interact with the DataFrame using SQL queries. For example, after creating the view, you can run the following query to analyze the elevation data:\n",
+ "\n",
+ "```python\n",
+ "result = spark.sql(\"SELECT * FROM elevation WHERE height > 1000\")\n",
+ "result.show()\n",
+ "```\n",
+ "\n",
+ "> *Note*: Temporary views only exist for the duration of the Spark session. Once the session ends, the view will no longer be available.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "11d88e63-128e-4dc1-b3dc-79fe7f8ff9dc",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:18:56.268051Z",
+ "iopub.status.busy": "2025-03-06T06:18:56.267852Z",
+ "iopub.status.idle": "2025-03-06T06:18:56.287892Z",
+ "shell.execute_reply": "2025-03-06T06:18:56.287430Z",
+ "shell.execute_reply.started": "2025-03-06T06:18:56.268038Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# This creates a temporary view from our DataFrame so it can be used in Spatial SQL queries\n",
+ "elevation.createOrReplaceTempView('elevation')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fdb9a12f-a528-4ea3-90fc-6270e64fc3e8",
+ "metadata": {},
+ "source": [
+ "# Step 5: **🍓 *I'm going to Strawberry Fields...***\n",
+ "\n",
+ "The following query calculates the elevation from a raster file of Central Park at the specific location of Strawberry Fields:\n",
+ "\n",
+ "```python\n",
+ "strawberry_fields = sedona.sql('''\n",
+ "select RS_Value(rast, ST_Point(-73.9751781, 40.7756813)) as elevation_in_feet\n",
+ "from elevation\n",
+ "''')\n",
+ "```\n",
+ "\n",
+ "#### 🔍 Explanation:\n",
+ "\n",
+ "- **`RS_Value(rast, ST_Point(...))`**: This function retrieves the value (e.g., elevation) from the raster file at a specified point. Here, the point is defined by its longitude and latitude coordinates (-73.9751781, 40.7756813).\n",
+ "- **`as elevation_in_feet`**: Assigns an alias to the output column, making it easier to interpret the results.\n",
+ "- **`from elevation`**: Specifies the raster DataFrame (registered as a temporary view) as the source of the query.\n",
+ "\n",
+ "#### 📊 Practical Use:\n",
+ "\n",
+ "This query allows you to extract elevation data or other raster-based values for specific locations, enabling precise spatial analysis. For example, the resulting DataFrame `strawberry_fields` will contain the elevation value in feet for the given coordinates.\n",
+ "\n",
+ "```python\n",
+ "strawberry_fields.show()\n",
+ "```\n",
+ "\n",
+ "> *Note*: This functionality is incredibly useful for point-specific raster queries, such as extracting elevation, temperature, or other environmental variables.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "09fa25f5-359d-4812-865c-704edefd44f8",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:19:02.100374Z",
+ "iopub.status.busy": "2025-03-06T06:19:02.100139Z",
+ "iopub.status.idle": "2025-03-06T06:19:02.116066Z",
+ "shell.execute_reply": "2025-03-06T06:19:02.115195Z",
+ "shell.execute_reply.started": "2025-03-06T06:19:02.100359Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# First we create the point geometry and then use the RS_Value function \n",
+ "# to get the raster value for that specific point location\n",
+ "\n",
+ "strawberry_fields = sedona.sql('''\n",
+ "SELECT\n",
+ " RS_Value(rast, ST_Point(-73.9751781, 40.7756813)) as elevation_in_feet\n",
+ "FROM\n",
+ " elevation \n",
+ "''')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "8224426f-010c-4e9a-b94e-a299801e61fd",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:20:17.150460Z",
+ "iopub.status.busy": "2025-03-06T06:20:17.150225Z",
+ "iopub.status.idle": "2025-03-06T06:20:36.710911Z",
+ "shell.execute_reply": "2025-03-06T06:20:36.710574Z",
+ "shell.execute_reply.started": "2025-03-06T06:20:17.150446Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+-----------------+\n",
+ "|elevation_in_feet|\n",
+ "+-----------------+\n",
+ "| 90.0|\n",
+ "+-----------------+\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Then we filter using a where clause and call `.show()` on the DataFrame to run the query and show the results\n",
+ "strawberry_fields.where(\"elevation_in_feet is not NULL\").show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b271c7ae-f5ca-4ba9-a891-da0dd3f0bf68",
+ "metadata": {},
+ "source": [
+ "# Step 6: **💅🏼 Visualizing our data using `SedonaKepler`**\n",
+ "\n",
+ "After processing your spatial data using Sedona, you can visualize it with SedonaKepler. For example:\n",
+ "\n",
+ "```python\n",
+ "from sedona.maps.SedonaKepler import SedonaKepler\n",
+ "\n",
+ "# Initialize a SedonaKepler map\n",
+ "map = SedonaKepler.create_map()\n",
+ "\n",
+ "# Visualize a DataFrame (e.g., NYC Buildings)\n",
+ "SedonaKepler.add_df(map, buildings, config= {\n",
+ " \"mapStyle\": \"dark\", # Choose map style\n",
+ " \"layers\": [\n",
+ " {\n",
+ " \"type\": \"polygon\", \n",
+ " \"name\": \"NYC Buildings\", \n",
+ " \"colorBy\": \"category\", \n",
+ " \"colorColumn\": \"PRIM_ID\", \n",
+ " \"heightColumn\": \"height_val\", \n",
+ " \"heightScale\": 1\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ ")\n",
+ "```\n",
+ "\n",
+ "> *Note*: We added a `config` file into the map set up so you can see some sample styles right away 💅🏼.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "796e1e33-9adc-47a0-9989-e139cde35cb6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "from sedona.maps.SedonaKepler import SedonaKepler\n",
+ "\n",
+ "# This code will load our map configuration so it can be read by SedonaKepler. \n",
+ "with open('map-config/config.json') as f:\n",
+ " # Load the JSON data into a dictionary\n",
+ " map_config = json.load(f)\n",
+ "\n",
+ "# These lines create the map with our configuration and add the dataframe, then render the map. \n",
+ "map = SedonaKepler.create_map(config=map_config)\n",
+ "SedonaKepler.add_df(map, buildings, 'NYC Buildings')\n",
+ "map"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fd4b35f7-404f-4fbe-b935-2b8651810836",
+ "metadata": {},
+ "source": [
+ "# Final Project: 🏢 Analyzing Building Elevations in Central Park\n",
+ "\n",
+ "This section explains the following query, which calculates the average elevation for buildings in New York City using a 1-ft Digital Elevation Model (DEM) of Central Park.\n",
+ "\n",
+ "### Code Overview\n",
+ "\n",
+ "```python\n",
+ "buildings_elevation = sedona.sql(f'''\n",
+ "WITH a AS (\n",
+ "SELECT\n",
+ " buildings.PROP_ADDR as name,\n",
+ " buildings.geom,\n",
+ " avg(RS_ZonalStats(elevation.rast, st_transform(buildings.geom, 'epsg:4326','epsg:2263'), 1, 'mean', true)) as elevation\n",
+ "FROM\n",
+ " buildings\n",
+ "JOIN\n",
+ " elevation\n",
+ "ON\n",
+ " RS_Intersects(elevation.rast, st_transform(buildings.geom, 'epsg:4326','epsg:2263'))\n",
+ "GROUP BY\n",
+ " buildings.PROP_ADDR, buildings.geom)\n",
+ "\n",
+ "SELECT\n",
+ " * \n",
+ "FROM \n",
+ " a \n",
+ "WHERE \n",
+ " elevation > 0\n",
+ "''')\n",
+ "```\n",
+ "\n",
+ "### 📊 Key Steps and Concepts\n",
+ "\n",
+ "#### 1. **Inputs**\n",
+ "- **`elevation`**: A 1-ft resolution DEM of Central Park, providing high-precision elevation data.\n",
+ "- **`buildings`**: A dataset of all buildings in New York City, including geometry (`geom`) and property address (`PROP_ADDR`).\n",
+ "\n",
+ "#### 2. **Coordinate Transformation**\n",
+ "- The building geometries are transformed from EPSG:4326 (geographic coordinates) to EPSG:2263 (New York State Plane coordinates) using `st_transform`. This ensures compatibility with the DEM raster.\n",
+ "\n",
+ "#### 3. **Zonal Statistics Calculation**\n",
+ "- **`RS_ZonalStats`** computes the mean elevation for each building geometry based on the DEM:\n",
+ " - **Raster Input**: `elevation.rast` (DEM raster file).\n",
+ " - **Vector Geometry**: Transformed building geometries.\n",
+ " - **Band**: The first band of the raster is used.\n",
+ " - **Statistic**: `mean` calculates the average elevation within the building footprint.\n",
+ " - **Ignore NoData**: `true` ensures invalid or missing data in the raster is excluded.\n",
+ "\n",
+ "#### 4. **Spatial Join**\n",
+ "- **`RS_Intersects`** ensures only buildings intersecting the DEM raster are included in the analysis.\n",
+ "\n",
+ "#### 5. **Filtering Results**\n",
+ "- The query filters out buildings with non-positive elevation values using `where elevation > 0`.\n",
+ "\n",
+ "#### 6. **Aggregation**\n",
+ "- Elevation values are grouped by building address (`PROP_ADDR`) and geometry to compute the average elevation for each unique building.\n",
+ "\n",
+ "### 📋 Output\n",
+ "The resulting DataFrame, `buildings_elevation`, contains:\n",
+ "- **`name`**: The property address of the building.\n",
+ "- **`geom`**: The building geometry.\n",
+ "- **`elevation`**: The average elevation of the building footprint in feet.\n",
+ "\n",
+ "### 🌟 Practical Use\n",
+ "This analysis combines raster (DEM) and vector (building footprints) data to derive meaningful insights about urban infrastructure. For example, it can be used for:\n",
+ "- Identifying buildings at risk of flooding based on elevation.\n",
+ "- Urban planning and construction in areas with varying terrain.\n",
+ "- Environmental impact studies within Central Park and surrounding areas.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e0657b98-8299-4a4a-818d-7ee1ed9d7c0b",
+ "metadata": {},
+ "source": [
+ "# Modify to get the elevation avg of all the buildings in central park"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "e499b735-03a0-44f9-a95f-493987442203",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:24:10.385725Z",
+ "iopub.status.busy": "2025-03-06T06:24:10.385511Z",
+ "iopub.status.idle": "2025-03-06T06:24:10.394534Z",
+ "shell.execute_reply": "2025-03-06T06:24:10.394202Z",
+ "shell.execute_reply.started": "2025-03-06T06:24:10.385710Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# First create our temporary view of the data\n",
+ "buildings.createOrReplaceTempView('buildings')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "7cb860ee-a16c-4e43-b2c4-075a55d2002b",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:24:14.690405Z",
+ "iopub.status.busy": "2025-03-06T06:24:14.690190Z",
+ "iopub.status.idle": "2025-03-06T06:24:15.302050Z",
+ "shell.execute_reply": "2025-03-06T06:24:15.301496Z",
+ "shell.execute_reply.started": "2025-03-06T06:24:14.690391Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+-------------+\n",
+ "|rs_srid(rast)|\n",
+ "+-------------+\n",
+ "| 2263|\n",
+ "+-------------+\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Here we will check the Spatial Reference ID (SRID) of the raster file\n",
+ "sedona.sql('SELECT RS_SRID(rast) FROM elevation limit 1').show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "023170a6-0fab-4523-b3ae-40d739b11d56",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:24:20.207365Z",
+ "iopub.status.busy": "2025-03-06T06:24:20.207059Z",
+ "iopub.status.idle": "2025-03-06T06:24:20.298307Z",
+ "shell.execute_reply": "2025-03-06T06:24:20.297793Z",
+ "shell.execute_reply.started": "2025-03-06T06:24:20.207351Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Below is the query we will which is explained in detail above.\n",
+ "\n",
+ "buildings_elevation = sedona.sql(f'''with a as (\n",
+ "SELECT\n",
+ " buildings.PROP_ADDR as name,\n",
+ " buildings.geom,\n",
+ " avg(RS_ZonalStats(elevation.rast, st_transform(buildings.geom, 'epsg:4326','epsg:2263'), 1, 'mean', true)) as elevation\n",
+ "FROM\n",
+ " buildings\n",
+ "JOIN\n",
+ " elevation\n",
+ "ON\n",
+ " RS_Intersects(elevation.rast, st_transform(buildings.geom, 'epsg:4326','epsg:2263'))\n",
+ "GROUP BY\n",
+ " buildings.PROP_ADDR, buildings.geom)\n",
+ "\n",
+ "SELECT * FROM a WHERE elevation > 0\n",
+ "''')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "164e2b2a-78f4-4be7-a126-bf0c9627ce01",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-03-06T06:24:23.575943Z",
+ "iopub.status.busy": "2025-03-06T06:24:23.575741Z",
+ "iopub.status.idle": "2025-03-06T06:24:36.006710Z",
+ "shell.execute_reply": "2025-03-06T06:24:36.006094Z",
+ "shell.execute_reply.started": "2025-03-06T06:24:23.575929Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "[Stage 31:===================================================>(1151 + 1) / 1152]\r"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "+--------------------+--------------------+------------------+\n",
+ "| name| geom| elevation|\n",
+ "+--------------------+--------------------+------------------+\n",
+ "| 1185 PARK AVENUE|MULTIPOLYGON (((-...| NaN|\n",
+ "| 830 5 AVENUE|MULTIPOLYGON (((-...| 45.04505110987552|\n",
+ "| 333 EAST 88 STREET|MULTIPOLYGON (((-...| NaN|\n",
+ "| 1000 PARK AVENUE|MULTIPOLYGON (((-...| NaN|\n",
+ "| 3 CENTER DRIVE|MULTIPOLYGON (((-...|59.092662762659316|\n",
+ "| 1245 2 AVENUE|MULTIPOLYGON (((-...| NaN|\n",
+ "| 830 5 AVENUE|MULTIPOLYGON (((-...| 69.41666666666667|\n",
+ "| 830 5 AVENUE|MULTIPOLYGON (((-...| 45.0256171531226|\n",
+ "| 830 5 AVENUE|MULTIPOLYGON (((-...| 46.00847457627118|\n",
+ "| 103 EAST 66 STREET|MULTIPOLYGON (((-...| NaN|\n",
+ "|1 CENTRAL PARK HE...|MULTIPOLYGON (((-...|59.349834983498354|\n",
+ "| NULL|MULTIPOLYGON (((-...|57.151720351390935|\n",
+ "|1183 LEXINGTON AV...|MULTIPOLYGON (((-...| NaN|\n",
+ "| 50 TERRACE DRIVE|MULTIPOLYGON (((-...| 95.0977297008547|\n",
+ "|122 79 ST TRANSVERSE|MULTIPOLYGON (((-...|131.00882352941176|\n",
+ "|2 CENTRAL PK NEAR...|MULTIPOLYGON (((-...| 47.04956896551724|\n",
+ "| 51 EAST DRIVE|MULTIPOLYGON (((-...| 18.16544829069018|\n",
+ "| 124 WEST 93 STREET|MULTIPOLYGON (((-...| NaN|\n",
+ "| 256 WEST 85 STREET|MULTIPOLYGON (((-...| NaN|\n",
+ "| 830 5 AVENUE|MULTIPOLYGON (((-...| 45.01784037558686|\n",
+ "+--------------------+--------------------+------------------+\n",
+ "only showing top 20 rows\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " \r"
+ ]
+ }
+ ],
+ "source": [
+ "# A quick check of our data using the .show() command on the Dataframe with the query results\n",
+ "buildings_elevation.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2e92b835-93ca-4fa7-8aff-bd206e3425e0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Then again load our map using the new map configuration file.\n",
+ "\n",
+ "with open('map-config/central_park_config.json') as f:\n",
+ " # Load the JSON data into a dictionary\n",
+ " park_config = json.load(f)\n",
+ "\n",
+ "map = SedonaKepler.create_map(config=park_config)\n",
+ "SedonaKepler.add_df(map, buildings_elevation, 'NYC Buildings')\n",
+ "map"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39f84092-d6e8-4e29-b9c7-090be5324820",
+ "metadata": {},
+ "source": [
+ "## 🎯 Ideas and Next Steps After Completing This Notebook\n",
+ "\n",
+ "Congratulations on completing this notebook! You’ve learned how to:\n",
+ "- Integrate raster and vector data for advanced geospatial analysis.\n",
+ "- Perform zonal statistics to derive meaningful insights from elevation and temperature datasets.\n",
+ "- Use Apache Sedona SQL to manipulate and query spatial data efficiently.\n",
+ "\n",
+ "### 🛠️ Experiment with Different Data Sources\n",
+ "- Use additional raster datasets, such as vegetation indices or precipitation maps, to enhance your analysis.\n",
+ "- Incorporate demographic or socioeconomic vector datasets to explore spatial relationships.\n",
+ "\n",
+ "> Did you know that Wherobots allows you to run [NDVI analysis](https://docs.wherobots.com/latest/api/wherobots-compute/sql/Raster-map-algebra/?h=ndvi#ndvi) and you can use [Overture Maps data](https://docs.wherobots.com/latest/tutorials/opendata/introduction/?h=overture#open-data-catalogs) from Wherobots DB.\n",
+ "\n",
+ "### 🔍 Try Advanced Apache Sedona Features\n",
+ "- Explore Sedona’s spatial join capabilities to analyze relationships between multiple vector datasets.\n",
+ "- Use Sedona’s advanced functions, like `ST_Buffer` or `ST_Within`, for proximity and containment analysis.\n",
+ "\n",
+ "> Check out our full function reference for [Apache Sedona here](https://docs.wherobots.com/latest/references/wherobotsdb/vector-data/Overview/).\n",
+ "\n",
+ "---\n",
+ "\n",
+ "## 📝 What’s Next: Tips for Loading Raster and Vector Data\n",
+ "\n",
+ "In the next notebook, we will dive deeper into the best practices for loading both raster and vector data into DataFrames. Here’s what you’ll learn:\n",
+ "\n",
+ "### 🌐 Loading Vector Data\n",
+ "- Step-by-step guides to loading vector data types into Apache Sedona DataFrames.\n",
+ "- This allows you to start querying the data with Spatial SQL or Python immediately.\n",
+ "\n",
+ "### 🗺️ Loading Raster Data\n",
+ "- Learn how to use Out-of-Database Rasters stored in remote cloud storage buckets (e.g., AWS Open Earth Data).\n",
+ "- Follow these two critical steps:\n",
+ " 1. Create a new raster dataset from a remote file.\n",
+ " 2. Explode and divide your Out-DB raster into tiles to optimize query performance.\n",
+ "\n",
+ "### 🛠️ Preparing for Spatial Joins\n",
+ "- Once your data is loaded, you’ll be ready to perform spatial joins at scale.\n",
+ "- We’ll cover the best strategies for combining raster and vector datasets to answer complex geospatial questions.\n",
+ "\n",
+ "With this foundation, you’ll be fully equipped to manage and query large-scale spatial datasets in Wherobots. Let’s get started!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0992785d-2a33-4c19-a383-3ac8e3c86bec",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.11.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}