{ "cells": [ { "cell_type": "markdown", "id": "6b92212e-0017-4e41-b5e9-23c8ca25057f", "metadata": {}, "source": [ "![](https://wherobots.com/wp-content/uploads/2023/12/Inline-Blue_Black_onWhite@3x.png)\n", "\n", "# Raster Data Analysis With Spatial SQL & Sedona\n", "\n", "Let's explore working with raster data in Sedona and Wherobots Cloud. This notebook covers:\n", "\n", "* loading a single GeoTiff as a raster\n", "* loading multiple GeoTiffs\n", "* tiling large rasters\n", "* raster / vector join operations\n", "* zonal statistics\n", "* saving rasters as Havasu tables\n", "* raster map algebra\n", "* exporting GeoTiffs\n", "\n", "You can find more information on working with rasters in the [documentation here.](https://docs.wherobots.services/1.2.1/references/sedonadb/raster-data/Overview/)" ] }, { "cell_type": "code", "execution_count": 1, "id": "eb0c09c5-da2a-4604-b535-9331f92287af", "metadata": {}, "outputs": [], "source": [ "from sedona.spark import *\n", "from pyspark.sql.functions import expr\n", "from IPython.display import display, HTML\n", "import rasterio\n", "from matplotlib import pyplot" ] }, { "cell_type": "code", "execution_count": 2, "id": "fd6d73d5-cad6-42b9-9e67-93dc6ee47ff6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Warning: Ignoring non-Spark config property: fs.s3a.aws.credentials.provider\n", "24/02/29 15:10:42 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n", "Setting default log level to \"WARN\".\n", "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n", "24/02/29 15:10:43 WARN MetricsConfig: Cannot locate configuration: tried hadoop-metrics2-s3a-file-system.properties,hadoop-metrics2.properties\n", "24/02/29 15:10:44 WARN S3ABlockOutputStream: Application invoked the Syncable API against stream writing to qjnq6fcbf1/spark-logs/spark-3ca049c8cf2c4c0fa188d596eefdc4d0.inprogress. This is unsupported\n", "24/02/29 15:11:26 WARN SedonaContext: Python files are not set. Sedona will not pre-load Python UDFs.\n" ] } ], "source": [ "config = SedonaContext.builder(). \\\n", " config(\"spark.hadoop.fs.s3a.bucket.wherobots-examples.aws.credentials.provider\",\"org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider\"). \\\n", " getOrCreate()\n", "\n", "sedona = SedonaContext.create(config)" ] }, { "cell_type": "markdown", "id": "5d710f7a-e318-4dc9-b235-acf3d6731ef3", "metadata": {}, "source": [ "## Raster Data Overview\n", "\n", "Raster data is gridded data where each pixel has one or more values associated with it (bands) and references a geographic location. Common raster data include aerial imagery, elevation models, precipitation maps, and population datasets.\n", "\n", "![](https://wherobots.com/wp-content/uploads/2024/02/raster_concept.png)\n", "\n", "*[image source: NEON](https://www.neonscience.org/)*\n", "\n", "\n", "When working with raster data in Sedona we store rasters and their associated metadata as rows in a table and query them using Spatial SQL.\n", "\n", "![](https://wherobots.com/wp-content/uploads/2024/02/earth_observation_table.png)\n", "\n", "\n", "One of the tools available to us when analyzing raster data is map algebra: performing calculations using the pixel values.\n", "\n", "![](https://wherobots.com/wp-content/uploads/2024/02/map_algebra.png)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "9fe84bbe-4344-42d5-9dc8-f53f3334ee03", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "1ba6ad2b-6f41-40fd-a1de-dd6baf899546", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "e7aa1827-33bd-4a39-bc65-5e9a958a85c8", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "9b9778a5-56ef-41df-a5da-22f121a8d146", "metadata": {}, "source": [ "## Load A Single Raster\n", "\n", "Sedona supports a number of raster data formats, including Arc/Info ASCII grid, NetCDF, and GeoTiff. See [raster loaders documentation page](https://docs.wherobots.services/1.2.1/references/sedonadb/raster-data/Raster-loader/) for more.\n", "\n", "Rasters can be loaded as \"out-of-database\" (out-db) rasters from a remote file path, \"in-database\" (in-db). Out-db allows for managing large raster datasets stored on cloud storage, efficient handling of remote data, while in-db is useful when the raster data needs to managed within the database (data integrity / access efficiency, etc)\n" ] }, { "cell_type": "markdown", "id": "9540e74a-b812-4a05-99b5-8d0f5aaa4a34", "metadata": {}, "source": [ "### `RS_FromPath` - Create an out-db raster from remote file path\n", "\n", "Let's load a single high-resolution aerial image from the [NEON dataset.](https://data.neonscience.org/data-products/DP3.30010.001)" ] }, { "cell_type": "code", "execution_count": 3, "id": "17de9fed-8843-4bab-890a-aaabf440471c", "metadata": {}, "outputs": [], "source": [ "file_url = \"s3://wherobots-examples/data/examples/NEON_ortho.tif\"\n", "neon_df = sedona.sql(f\"SELECT RS_FromPath('{file_url}') AS raster\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "eec75806-5107-4f3e-8c12-08c1acf29d8e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- raster: raster (nullable = true)\n", "\n" ] } ], "source": [ "neon_df.createOrReplaceTempView(\"neon\")\n", "neon_df.printSchema()" ] }, { "cell_type": "code", "execution_count": 5, "id": "9f59b15b-3f0c-4afc-b44a-8bf4485d9856", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+---------------------------------------+\n", "|raster |\n", "+---------------------------------------+\n", "|LazyLoadOutDbGridCoverage2D[not loaded]|\n", "+---------------------------------------+\n", "\n" ] } ], "source": [ "neon_df.show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 6, "id": "f3216f1c-285f-4ec0-aff0-6464cde9cba6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[Stage 4:> (0 + 1) / 1]\r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+------------------------------------------------------------------------+\n", "|rs_metadata(raster) |\n", "+------------------------------------------------------------------------+\n", "|[470000.0, 7228000.0, 1000.0, 1000.0, 1.0, -1.0, 0.0, 0.0, 32606.0, 3.0]|\n", "+------------------------------------------------------------------------+\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "sedona.sql(\"SELECT RS_MetaData(raster) from neon\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 7, "id": "8d925782-1eec-4617-86c0-8da8bd17c104", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+\n", "|rs_numbands(raster)|\n", "+-------------------+\n", "| 3|\n", "+-------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_NumBands(raster) FROM neon\").show()" ] }, { "cell_type": "code", "execution_count": 8, "id": "76d6d7e9-7552-4788-8dce-46e1bd4fed2d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
rs_asimage(raster, 500)
0
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "htmlDf = sedona.sql(\"SELECT RS_AsImage(raster, 500) FROM neon\")\n", "SedonaUtils.display_image(htmlDf)" ] }, { "cell_type": "code", "execution_count": 9, "id": "9a78f99d-3e26-41f0-855b-588339f11b66", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------------------------------------------------------------+\n", "|rs_values(raster, array(st_setsrid(st_point(470000, 7227880), 32606)), 2)|\n", "+-------------------------------------------------------------------------+\n", "|[104.0] |\n", "+-------------------------------------------------------------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_Values(raster, Array(ST_SetSRID(ST_Point(470000, 7227880), 32606)), 2) FROM neon\").show(truncate=False)" ] }, { "cell_type": "markdown", "id": "9bedf489-422c-4829-b126-8dbb6c4c483f", "metadata": {}, "source": [ "### Map Algebra Operations\n", "\n", "Performing raster math is one of the most common and powerful raster workflows (used for example to compute spectral indexes). Sedona supports a number of band-specific raster math operations such as:\n", "\n", "* `RS_Add`, `RS_Divide`, `RS_Mean`, `RS_NormalizedDifference`, etc\n", "* [`RS_MapAlgebra`](https://docs.wherobots.services/1.2.1/references/sedonadb/raster-data/Raster-map-algebra/)\n", "\n", "\n", "### [`RS_MapAlgebra`](https://docs.wherobots.services/1.2.1/references/sedonadb/raster-data/Raster-map-algebra/)\n", "\n", "Used to apply a map algebra script on a raster (or multiple rasters). For example to calculate NDVI or AWEI. \n", "\n", "Let's calculate the Normalized Difference Greenness Index (Escadafal & Huete 1991) for our raster \n", "\n", "\\begin{equation*}\n", "{NDGI} = \\frac{G-R}{G+R}\n", "\\end{equation*}\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "c1c337ea-06a4-4e01-9b55-5a93dcc001f9", "metadata": {}, "outputs": [], "source": [ "ndgi_df = sedona.sql(\"\"\"\n", "SELECT \n", " RS_MapAlgebra(raster, 'D', 'out = ((rast[1] - rast[0]) / (rast[1] + rast[0]));') \n", "AS raster\n", "FROM neon\n", "\"\"\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "9ff05c1d-5768-41b9-b4ae-c36dd7d3b0ca", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- raster: raster (nullable = true)\n", "\n" ] } ], "source": [ "ndgi_df.createOrReplaceTempView(\"ndgi\")\n", "ndgi_df.printSchema()" ] }, { "cell_type": "code", "execution_count": 12, "id": "18a4f828-737e-4b34-a3ad-c63dce118957", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+\n", "|rs_numbands(raster)|\n", "+-------------------+\n", "| 1|\n", "+-------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_NumBands(raster) FROM ndgi\").show()" ] }, { "cell_type": "code", "execution_count": 13, "id": "f124f4f0-64e1-460d-b438-6441a2af080c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+----------------------------------------------------------------------------------------------------------------------+\n", "|rs_summarystats(raster) |\n", "+----------------------------------------------------------------------------------------------------------------------+\n", "|[1000000.0, -10863.97160595989, -0.010863971605958938, 0.045695423898689726, -0.1493212669683258, 0.18421052631578946]|\n", "+----------------------------------------------------------------------------------------------------------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_SummaryStats(raster) FROM ndgi\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 14, "id": "873856bc-534f-4849-8992-0002cbcd8b0f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------------------------------------------------------------+\n", "|rs_values(raster, array(st_setsrid(st_point(470000, 7227880), 32606)), 1)|\n", "+-------------------------------------------------------------------------+\n", "|[-0.09956709956709957] |\n", "+-------------------------------------------------------------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_Values(raster, Array(ST_SetSRID(ST_Point(470000, 7227880), 32606)), 1) FROM ndgi\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 15, "id": "6148d81b-56e0-4e0d-bf96-848a8cfb9e67", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------------------------------------------------------------+\n", "|rs_values(raster, array(st_setsrid(st_point(470700, 7228000), 32606)), 1)|\n", "+-------------------------------------------------------------------------+\n", "|[0.03636363636363636] |\n", "+-------------------------------------------------------------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_Values(raster, Array(ST_SetSRID(ST_Point(470700, 7228000), 32606)), 1) FROM ndgi\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 16, "id": "48bba658-7a8b-4e98-a55c-8f2e5e37c9d9", "metadata": {}, "outputs": [], "source": [ "binary_raster_df = sedona.sql(\"SELECT RS_AsGeoTiff(raster) AS raster FROM ndgi\")" ] }, { "cell_type": "code", "execution_count": 17, "id": "5c34f202-138f-4046-b7ed-f31c6bb5f62f", "metadata": {}, "outputs": [], "source": [ "binary_raster_df.write.format(\"raster\").mode(\"overwrite\").save(\"ndgi.tif\")" ] }, { "cell_type": "code", "execution_count": null, "id": "4d4f7c5a-7d15-4369-bb31-d6d6e3b0f99c", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "ca7a86c2-1d8f-4555-a60d-0024524468c1", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "44da77fe-7600-40a5-9ba6-3bf969907dd2", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "2fc2fd41-61c1-4de7-ba25-cc2adbd66976", "metadata": {}, "source": [ "## Load Multiple Rasters\n", "\n", "Previously we saw loading a single raster into a single row. We typically work with many rasters across many rows. Let's load a raster dataset from the [WorldClim historical climate dataset](https://www.worldclim.org/data/worldclim21.html) of precipitation from 1970-2000. Each raster file represents the average precipitation across all years for each month of the year.\n" ] }, { "cell_type": "code", "execution_count": 18, "id": "4d6c93cb-17ae-4d78-94ed-968cf5263097", "metadata": {}, "outputs": [], "source": [ "PREC_URL = \"s3://wherobots-examples/data/examples/world_clim/wc2.1_10m_prec\" #/wc2.1_10m_prec_01.tif" ] }, { "cell_type": "code", "execution_count": 19, "id": "0d4d8e25-3354-4efa-844e-9ff383c82362", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------------------+-------------------+------+--------------------+\n", "| path| modificationTime|length| content|\n", "+--------------------+-------------------+------+--------------------+\n", "|s3://wherobots-ex...|2024-02-28 19:59:56|669568|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:55|642783|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:57|632536|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:56|628584|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:58|624869|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:58|619008|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 20:00:00|615937|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:59|615576|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:54|594226|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 19:59:53|581807|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 20:00:00|576683|[49 49 2A 00 08 0...|\n", "|s3://wherobots-ex...|2024-02-28 20:00:01|561700|[49 49 2A 00 08 0...|\n", "+--------------------+-------------------+------+--------------------+\n", "\n" ] } ], "source": [ "rawDf = sedona.read.format(\"binaryFile\").load(PREC_URL + \"/*.tif\")\n", "rawDf.createOrReplaceTempView(\"rawdf\")\n", "rawDf.show()" ] }, { "cell_type": "code", "execution_count": 20, "id": "52813c05-c90f-484b-8f53-da400b796d56", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- raster: raster (nullable = true)\n", " |-- month: integer (nullable = true)\n", "\n" ] } ], "source": [ "rasterDf = sedona.sql(\"\"\"\n", "SELECT \n", " RS_FromGeoTiff(content) AS raster, \n", " Int(regexp_extract(path, '(.*)([0-9]{2}).tif', 2)) AS month\n", "FROM rawdf\n", "\"\"\")\n", "\n", "rasterDf.createOrReplaceTempView(\"prec\")\n", "rasterDf.printSchema()" ] }, { "cell_type": "code", "execution_count": null, "id": "01bd6e66-4983-4b59-b5b3-ba6e466476ac", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 21, "id": "07224a5f-998c-4d4a-9268-cb8a55366e31", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ " \r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+------------------------------------------------------------------------------------------------+\n", "|rs_metadata(raster) |\n", "+------------------------------------------------------------------------------------------------+\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "|[-180.0, 90.0, 2160.0, 1080.0, 0.16666666666666666, -0.16666666666666666, 0.0, 0.0, 4326.0, 1.0]|\n", "+------------------------------------------------------------------------------------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_MetaData(raster) FROM prec\").show(truncate=False) " ] }, { "cell_type": "code", "execution_count": 22, "id": "d6cf5067-832a-4989-8725-fee96c545062", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[Stage 19:> (0 + 6) / 6]\r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+-----+---------------------------------------------------------------------------+\n", "|month|rs_summarystats(raster) |\n", "+-----+---------------------------------------------------------------------------+\n", "|1 |[808053.0, 3.2816839E7, 40.612235831036806, 71.58202261528564, 0.0, 908.0] |\n", "|2 |[808053.0, 3.110572E7, 38.49465319724863, 65.22884915327343, 0.0, 793.0] |\n", "|3 |[808053.0, 3.4943215E7, 43.24371668684569, 67.88342263061789, 0.0, 720.0] |\n", "|4 |[808053.0, 3.4283833E7, 42.42770338082592, 61.129070691979166, 0.0, 1004.0]|\n", "|5 |[808053.0, 3.6639583E7, 45.34304432999431, 63.51998004686114, 0.0, 2068.0] |\n", "|6 |[808053.0, 3.8714648E7, 47.9110256382872, 72.94226238575892, 0.0, 2210.0] |\n", "|7 |[808053.0, 4.6393435E7, 57.413851566716545, 82.74978674918007, 0.0, 2381.0]|\n", "|8 |[808053.0, 4.8515628E7, 60.040155782001115, 76.31015675449926, 0.0, 1674.0]|\n", "|9 |[808053.0, 3.9648388E7, 49.06656865321915, 66.55061748894705, 0.0, 1955.0] |\n", "|10 |[808053.0, 3.5971104E7, 44.51577309906402, 61.76314020099509, 0.0, 2328.0] |\n", "|11 |[808053.0, 3.2569273E7, 40.305862362897145, 61.227354819810515, 0.0, 718.0]|\n", "|12 |[808053.0, 3.2873464E7, 40.682311680044606, 67.51048011158271, 0.0, 806.0] |\n", "+-----+---------------------------------------------------------------------------+\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "sedona.sql(\"SELECT month, RS_SummaryStats(raster) FROM prec ORDER BY month ASC\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 23, "id": "f0a5c300-44aa-4f59-a1c8-dbb9193ea136", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-----+--------+\n", "|month|avg_prec|\n", "+-----+--------+\n", "|1 |[43.0] |\n", "|2 |[27.0] |\n", "|3 |[31.0] |\n", "|4 |[31.0] |\n", "|5 |[50.0] |\n", "|6 |[49.0] |\n", "|7 |[27.0] |\n", "|8 |[31.0] |\n", "|9 |[31.0] |\n", "|10 |[29.0] |\n", "|11 |[35.0] |\n", "|12 |[40.0] |\n", "+-----+--------+\n", "\n" ] } ], "source": [ "sedona.sql(\"\"\"\n", "SELECT \n", " month, \n", " RS_Values(raster, Array(ST_POINT(-113.9940, 46.8721))) AS avg_prec \n", " FROM prec ORDER BY month ASC\n", "\"\"\").show(truncate=False)" ] }, { "cell_type": "markdown", "id": "c75c89dd-007b-483f-881d-ec40339a369d", "metadata": {}, "source": [ "### Zonal Statistics\n", "\n", "Zonal statistics involves joining vector geometries to the raster and calculating statistical or aggregating values based on the pixel values within each vector geometry." ] }, { "cell_type": "code", "execution_count": 24, "id": "bf1c6c42-d6fc-4d08-aec3-7bfb42a0b32b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- geometry: geometry (nullable = true)\n", " |-- featurecla: string (nullable = true)\n", " |-- scalerank: string (nullable = true)\n", " |-- LABELRANK: string (nullable = true)\n", " |-- SOVEREIGNT: string (nullable = true)\n", " |-- SOV_A3: string (nullable = true)\n", " |-- ADM0_DIF: string (nullable = true)\n", " |-- LEVEL: string (nullable = true)\n", " |-- TYPE: string (nullable = true)\n", " |-- TLC: string (nullable = true)\n", " |-- ADMIN: string (nullable = true)\n", " |-- ADM0_A3: string (nullable = true)\n", " |-- GEOU_DIF: string (nullable = true)\n", " |-- GEOUNIT: string (nullable = true)\n", " |-- GU_A3: string (nullable = true)\n", " |-- SU_DIF: string (nullable = true)\n", " |-- SUBUNIT: string (nullable = true)\n", " |-- SU_A3: string (nullable = true)\n", " |-- BRK_DIFF: string (nullable = true)\n", " |-- NAME: string (nullable = true)\n", " |-- NAME_LONG: string (nullable = true)\n", " |-- BRK_A3: string (nullable = true)\n", " |-- BRK_NAME: string (nullable = true)\n", " |-- BRK_GROUP: string (nullable = true)\n", " |-- ABBREV: string (nullable = true)\n", " |-- POSTAL: string (nullable = true)\n", " |-- FORMAL_EN: string (nullable = true)\n", " |-- FORMAL_FR: string (nullable = true)\n", " |-- NAME_CIAWF: string (nullable = true)\n", " |-- NOTE_ADM0: string (nullable = true)\n", " |-- NOTE_BRK: string (nullable = true)\n", " |-- NAME_SORT: string (nullable = true)\n", " |-- NAME_ALT: string (nullable = true)\n", " |-- MAPCOLOR7: string (nullable = true)\n", " |-- MAPCOLOR8: string (nullable = true)\n", " |-- MAPCOLOR9: string (nullable = true)\n", " |-- MAPCOLOR13: string (nullable = true)\n", " |-- POP_EST: string (nullable = true)\n", " |-- POP_RANK: string (nullable = true)\n", " |-- POP_YEAR: string (nullable = true)\n", " |-- GDP_MD: string (nullable = true)\n", " |-- GDP_YEAR: string (nullable = true)\n", " |-- ECONOMY: string (nullable = true)\n", " |-- INCOME_GRP: string (nullable = true)\n", " |-- FIPS_10: string (nullable = true)\n", " |-- ISO_A2: string (nullable = true)\n", " |-- ISO_A2_EH: string (nullable = true)\n", " |-- ISO_A3: string (nullable = true)\n", " |-- ISO_A3_EH: string (nullable = true)\n", " |-- ISO_N3: string (nullable = true)\n", " |-- ISO_N3_EH: string (nullable = true)\n", " |-- UN_A3: string (nullable = true)\n", " |-- WB_A2: string (nullable = true)\n", " |-- WB_A3: string (nullable = true)\n", " |-- WOE_ID: string (nullable = true)\n", " |-- WOE_ID_EH: string (nullable = true)\n", " |-- WOE_NOTE: string (nullable = true)\n", " |-- ADM0_ISO: string (nullable = true)\n", " |-- ADM0_DIFF: string (nullable = true)\n", " |-- ADM0_TLC: string (nullable = true)\n", " |-- ADM0_A3_US: string (nullable = true)\n", " |-- ADM0_A3_FR: string (nullable = true)\n", " |-- ADM0_A3_RU: string (nullable = true)\n", " |-- ADM0_A3_ES: string (nullable = true)\n", " |-- ADM0_A3_CN: string (nullable = true)\n", " |-- ADM0_A3_TW: string (nullable = true)\n", " |-- ADM0_A3_IN: string (nullable = true)\n", " |-- ADM0_A3_NP: string (nullable = true)\n", " |-- ADM0_A3_PK: string (nullable = true)\n", " |-- ADM0_A3_DE: string (nullable = true)\n", " |-- ADM0_A3_GB: string (nullable = true)\n", " |-- ADM0_A3_BR: string (nullable = true)\n", " |-- ADM0_A3_IL: string (nullable = true)\n", " |-- ADM0_A3_PS: string (nullable = true)\n", " |-- ADM0_A3_SA: string (nullable = true)\n", " |-- ADM0_A3_EG: string (nullable = true)\n", " |-- ADM0_A3_MA: string (nullable = true)\n", " |-- ADM0_A3_PT: string (nullable = true)\n", " |-- ADM0_A3_AR: string (nullable = true)\n", " |-- ADM0_A3_JP: string (nullable = true)\n", " |-- ADM0_A3_KO: string (nullable = true)\n", " |-- ADM0_A3_VN: string (nullable = true)\n", " |-- ADM0_A3_TR: string (nullable = true)\n", " |-- ADM0_A3_ID: string (nullable = true)\n", " |-- ADM0_A3_PL: string (nullable = true)\n", " |-- ADM0_A3_GR: string (nullable = true)\n", " |-- ADM0_A3_IT: string (nullable = true)\n", " |-- ADM0_A3_NL: string (nullable = true)\n", " |-- ADM0_A3_SE: string (nullable = true)\n", " |-- ADM0_A3_BD: string (nullable = true)\n", " |-- ADM0_A3_UA: string (nullable = true)\n", " |-- ADM0_A3_UN: string (nullable = true)\n", " |-- ADM0_A3_WB: string (nullable = true)\n", " |-- CONTINENT: string (nullable = true)\n", " |-- REGION_UN: string (nullable = true)\n", " |-- SUBREGION: string (nullable = true)\n", " |-- REGION_WB: string (nullable = true)\n", " |-- NAME_LEN: string (nullable = true)\n", " |-- LONG_LEN: string (nullable = true)\n", " |-- ABBREV_LEN: string (nullable = true)\n", " |-- TINY: string (nullable = true)\n", " |-- HOMEPART: string (nullable = true)\n", " |-- MIN_ZOOM: string (nullable = true)\n", " |-- MIN_LABEL: string (nullable = true)\n", " |-- MAX_LABEL: string (nullable = true)\n", " |-- LABEL_X: string (nullable = true)\n", " |-- LABEL_Y: string (nullable = true)\n", " |-- NE_ID: string (nullable = true)\n", " |-- WIKIDATAID: string (nullable = true)\n", " |-- NAME_AR: string (nullable = true)\n", " |-- NAME_BN: string (nullable = true)\n", " |-- NAME_DE: string (nullable = true)\n", " |-- NAME_EN: string (nullable = true)\n", " |-- NAME_ES: string (nullable = true)\n", " |-- NAME_FA: string (nullable = true)\n", " |-- NAME_FR: string (nullable = true)\n", " |-- NAME_EL: string (nullable = true)\n", " |-- NAME_HE: string (nullable = true)\n", " |-- NAME_HI: string (nullable = true)\n", " |-- NAME_HU: string (nullable = true)\n", " |-- NAME_ID: string (nullable = true)\n", " |-- NAME_IT: string (nullable = true)\n", " |-- NAME_JA: string (nullable = true)\n", " |-- NAME_KO: string (nullable = true)\n", " |-- NAME_NL: string (nullable = true)\n", " |-- NAME_PL: string (nullable = true)\n", " |-- NAME_PT: string (nullable = true)\n", " |-- NAME_RU: string (nullable = true)\n", " |-- NAME_SV: string (nullable = true)\n", " |-- NAME_TR: string (nullable = true)\n", " |-- NAME_UK: string (nullable = true)\n", " |-- NAME_UR: string (nullable = true)\n", " |-- NAME_VI: string (nullable = true)\n", " |-- NAME_ZH: string (nullable = true)\n", " |-- NAME_ZHT: string (nullable = true)\n", " |-- FCLASS_ISO: string (nullable = true)\n", " |-- TLC_DIFF: string (nullable = true)\n", " |-- FCLASS_TLC: string (nullable = true)\n", " |-- FCLASS_US: string (nullable = true)\n", " |-- FCLASS_FR: string (nullable = true)\n", " |-- FCLASS_RU: string (nullable = true)\n", " |-- FCLASS_ES: string (nullable = true)\n", " |-- FCLASS_CN: string (nullable = true)\n", " |-- FCLASS_TW: string (nullable = true)\n", " |-- FCLASS_IN: string (nullable = true)\n", " |-- FCLASS_NP: string (nullable = true)\n", " |-- FCLASS_PK: string (nullable = true)\n", " |-- FCLASS_DE: string (nullable = true)\n", " |-- FCLASS_GB: string (nullable = true)\n", " |-- FCLASS_BR: string (nullable = true)\n", " |-- FCLASS_IL: string (nullable = true)\n", " |-- FCLASS_PS: string (nullable = true)\n", " |-- FCLASS_SA: string (nullable = true)\n", " |-- FCLASS_EG: string (nullable = true)\n", " |-- FCLASS_MA: string (nullable = true)\n", " |-- FCLASS_PT: string (nullable = true)\n", " |-- FCLASS_AR: string (nullable = true)\n", " |-- FCLASS_JP: string (nullable = true)\n", " |-- FCLASS_KO: string (nullable = true)\n", " |-- FCLASS_VN: string (nullable = true)\n", " |-- FCLASS_TR: string (nullable = true)\n", " |-- FCLASS_ID: string (nullable = true)\n", " |-- FCLASS_PL: string (nullable = true)\n", " |-- FCLASS_GR: string (nullable = true)\n", " |-- FCLASS_IT: string (nullable = true)\n", " |-- FCLASS_NL: string (nullable = true)\n", " |-- FCLASS_SE: string (nullable = true)\n", " |-- FCLASS_BD: string (nullable = true)\n", " |-- FCLASS_UA: string (nullable = true)\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "24/02/29 15:11:44 WARN package: Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.sql.debug.maxToStringFields'.\n" ] } ], "source": [ "countries = ShapefileReader.readToGeometryRDD(sedona, 's3://wherobots-examples/data/examples/natural_earth/ne_10m_admin_0_countries')\n", "countries_df = Adapter.toDf(countries, sedona)\n", "countries_df.createOrReplaceTempView(\"countries\")\n", "countries_df.printSchema()" ] }, { "cell_type": "code", "execution_count": 25, "id": "cf009507-0134-4659-ac28-87500d69404d", "metadata": {}, "outputs": [], "source": [ "world_prec_df = sedona.sql(\"\"\"\n", "SELECT \n", " sum(RS_ZonalStats(prec.raster, countries.geometry, 1, 'avg', true)) AS yearly_avg_prec, \n", " any_value(countries.geometry), \n", " countries.name\n", "FROM prec, countries\n", "GROUP BY name\n", "ORDER BY yearly_avg_prec DESC\n", "\"\"\")" ] }, { "cell_type": "code", "execution_count": 26, "id": "899ca7e2-6874-431c-b456-7628cbd33afb", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ " \r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+------------------+--------------------+--------------------+\n", "| yearly_avg_prec| any_value(geometry)| name|\n", "+------------------+--------------------+--------------------+\n", "| 4937.5|MULTIPOLYGON (((1...| Micronesia|\n", "| 3526.0|MULTIPOLYGON (((1...| Palau|\n", "| 3378.75|MULTIPOLYGON (((-...| Samoa|\n", "| 3345.6875|MULTIPOLYGON (((1...| Brunei|\n", "| 3234.474358974359|MULTIPOLYGON (((1...| Solomon Is.|\n", "| 3111.0|MULTIPOLYGON (((-...| Saint Helena|\n", "| 3008.0|MULTIPOLYGON (((-...|Wallis and Futuna...|\n", "| 2988.550872093023|MULTIPOLYGON (((1...| Papua New Guinea|\n", "|2934.6285714285714|MULTIPOLYGON (((1...| Vanuatu|\n", "|2881.2202505219207|MULTIPOLYGON (((1...| Malaysia|\n", "| 2831.0|MULTIPOLYGON (((-...| Costa Rica|\n", "| 2807.0|MULTIPOLYGON (((-...| Faeroe Is.|\n", "|2733.1463857609974|MULTIPOLYGON (((1...| Indonesia|\n", "|2717.5348837209303|MULTIPOLYGON (((-...| Sierra Leone|\n", "| 2675.306306306306|MULTIPOLYGON (((-...| Panama|\n", "| 2656.390070921986|POLYGON ((-11.476...| Liberia|\n", "| 2631.974466806844|MULTIPOLYGON (((-...| Colombia|\n", "|2560.3461538461534|MULTIPOLYGON (((-...| Fiji|\n", "|2555.6666666666665|MULTIPOLYGON (((6...|São Tomé and Pr...|\n", "|2525.6388261851025|MULTIPOLYGON (((1...| Philippines|\n", "+------------------+--------------------+--------------------+\n", "only showing top 20 rows\n", "\n" ] } ], "source": [ "world_prec_df.dropna().show()" ] }, { "cell_type": "code", "execution_count": 27, "id": "67b88ab4-f8dc-4531-a192-0289c7c020b8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "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": "8bc1bc88149c4c1eb075bbb974fde6bd", "version_major": 2, "version_minor": 0 }, "text/plain": [ "KeplerGl(data={'unnamed': {'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "SedonaKepler.create_map(world_prec_df.dropna())" ] }, { "cell_type": "code", "execution_count": null, "id": "f44b0d61-a71a-4547-b8a4-46d231a6b761", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "947f53a5-6390-43cf-bff7-ad60a64420ff", "metadata": {}, "source": [ "## Tiling Rasters\n", "\n", "If we have large rasters we typically want to break them up into multiple tiles to improve the efficiency of raster operations. Let's take a look at an example using a [dataset from NOAA of night time visible lights](https://www.ncei.noaa.gov/products/dmsp-operational-linescan-system)." ] }, { "cell_type": "code", "execution_count": null, "id": "bee8f544-32d4-42c8-9f05-fbfe8545f45b", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 28, "id": "3ba30654-6e7d-46cb-a11b-1a67511db991", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "src = rasterio.open(\"data/F101993.v4b.global.stable_lights.avg_vis.tif\")\n", "array = src.read(1)\n", "pyplot.imshow(array, cmap='pink')" ] }, { "cell_type": "code", "execution_count": null, "id": "8cd69f0f-7b7f-4898-8a25-c3552641c033", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 29, "id": "3121dbed-0d29-45c0-8974-422e6ba5c11c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+---------------------------------------+\n", "|raster |\n", "+---------------------------------------+\n", "|LazyLoadOutDbGridCoverage2D[not loaded]|\n", "+---------------------------------------+\n", "\n" ] } ], "source": [ "f10_1993_uri = \"s3://wherobots-examples/data/examples/DMSP_OLS/F101993.v4b.global.stable_lights.avg_vis.tif\"\n", "f10_1993_df = sedona.sql(f\"SELECT RS_FromPath('{f10_1993_uri}') AS raster\")\n", "f10_1993_df.createOrReplaceTempView(\"f10_1993\")\n", "f10_1993_df.show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 30, "id": "c48c9a9b-b0e1-4ac5-a238-ab7e61aaf329", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+---+---+--------------------+\n", "| x| y| tile|\n", "+---+---+--------------------+\n", "| 0| 0|OutDbGridCoverage...|\n", "| 1| 0|OutDbGridCoverage...|\n", "| 2| 0|OutDbGridCoverage...|\n", "| 3| 0|OutDbGridCoverage...|\n", "| 4| 0|OutDbGridCoverage...|\n", "+---+---+--------------------+\n", "only showing top 5 rows\n", "\n" ] } ], "source": [ "tile_df = sedona.sql(\"SELECT RS_TileExplode(raster, 256, 256) AS (x, y, tile) FROM f10_1993\")\n", "tile_df.show(5)" ] }, { "cell_type": "code", "execution_count": 31, "id": "21c0d452-0ec5-49e9-a095-8b8c6727bb7c", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "SLF4J: Failed to load class \"org.slf4j.impl.StaticLoggerBinder\". \n", "SLF4J: Defaulting to no-operation (NOP) logger implementation\n", "SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.\n" ] } ], "source": [ "sedona.sql(\"DROP TABLE IF EXISTS wherobots.test_db.f10_1993\")\n", "tile_df.writeTo(\"wherobots.test_db.f10_1993\").create()" ] }, { "cell_type": "code", "execution_count": 32, "id": "50a89eae-d9c4-432e-83ec-d2fbc13c559b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "11154" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sedona.table(\"wherobots.test_db.f10_1993\").count()" ] }, { "cell_type": "code", "execution_count": 33, "id": "9f81be22-5cf2-4629-aa1b-e061d3c7961d", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ " \r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+---+---+--------------------+\n", "| x| y| tile|\n", "+---+---+--------------------+\n", "| 0| 0|OutDbGridCoverage...|\n", "| 1| 0|OutDbGridCoverage...|\n", "| 2| 0|OutDbGridCoverage...|\n", "| 3| 0|OutDbGridCoverage...|\n", "| 4| 0|OutDbGridCoverage...|\n", "| 5| 0|OutDbGridCoverage...|\n", "| 6| 0|OutDbGridCoverage...|\n", "| 7| 0|OutDbGridCoverage...|\n", "| 8| 0|OutDbGridCoverage...|\n", "| 9| 0|OutDbGridCoverage...|\n", "| 10| 0|OutDbGridCoverage...|\n", "| 11| 0|OutDbGridCoverage...|\n", "| 12| 0|OutDbGridCoverage...|\n", "| 13| 0|OutDbGridCoverage...|\n", "| 14| 0|OutDbGridCoverage...|\n", "| 15| 0|OutDbGridCoverage...|\n", "| 16| 0|OutDbGridCoverage...|\n", "| 17| 0|OutDbGridCoverage...|\n", "| 18| 0|OutDbGridCoverage...|\n", "| 19| 0|OutDbGridCoverage...|\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": "cc9e60a71c604c95831385d037be3d0c", "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…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sedona.table(\"wherobots.test_db.f10_1993\").show()\n", "\n", "tiledMap = SedonaKepler.create_map()\n", "SedonaKepler.add_df(tiledMap, sedona.table(\"wherobots.test_db.f10_1993\").withColumn(\"tile\", expr(\"RS_Envelope(tile)\")), name=\"tiles\")\n", "tiledMap" ] }, { "cell_type": "code", "execution_count": 34, "id": "0e42bde7-cdcf-4b69-a9a1-6743c9dfddec", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+\n", "|rs_numbands(raster)|\n", "+-------------------+\n", "| 1|\n", "+-------------------+\n", "\n" ] } ], "source": [ "sedona.sql(\"SELECT RS_NumBands(raster) FROM f10_1993\").show()" ] }, { "cell_type": "code", "execution_count": 35, "id": "ecc392d8-a8d9-4aba-aa38-7bc7ba520730", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ " \r" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
rs_asimage(tile, 200)rs_envelope(tile)
0POLYGON ((-180.00416666665 72.87083334185, -180.00416666665 75.00416666665, -177.87083334185 75.00416666665, -177.87083334185 72.87083334185, -180.00416666665 72.87083334185))
1POLYGON ((-177.87083334185002 72.87083334185, -177.87083334185002 75.00416666665, -175.73750001705 75.00416666665, -175.73750001705 72.87083334185, -177.87083334185002 72.87083334185))
2POLYGON ((-175.73750001705 72.87083334185, -175.73750001705 75.00416666665, -173.60416669224998 75.00416666665, -173.60416669224998 72.87083334185, -175.73750001705 72.87083334185))
3POLYGON ((-173.60416669225 72.87083334185, -173.60416669225 75.00416666665, -171.47083336744998 75.00416666665, -171.47083336744998 72.87083334185, -173.60416669225 72.87083334185))
4POLYGON ((-171.47083336745 72.87083334185, -171.47083336745 75.00416666665, -169.33750004265 75.00416666665, -169.33750004265 72.87083334185, -171.47083336745 72.87083334185))
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(HTML(sedona.table(\"wherobots.test_db.f10_1993\").selectExpr(\"RS_AsImage(tile, 200)\", \"RS_Envelope(tile)\").limit(5).toPandas().to_html(escape=False)))" ] }, { "cell_type": "code", "execution_count": 36, "id": "3a936236-f61c-4d5e-ae66-2da37663ae10", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[Stage 44:> (0 + 1) / 1]\r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+----------------------------------------------------+\n", "|rs_values(tile, array(st_point(-113.9940, 46.8721)))|\n", "+----------------------------------------------------+\n", "|[63.0] |\n", "+----------------------------------------------------+\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "sedona.sql(\"\"\"\n", "WITH matched_tile AS (\n", " SELECT * FROM wherobots.test_db.f10_1993 \n", " WHERE RS_Intersects(tile, ST_POINT(-113.9940, 46.8721))\n", ")\n", "\n", "SELECT RS_Values(tile, Array(ST_POINT(-113.9940, 46.8721))) \n", "FROM matched_tile\n", "\n", "\"\"\").show(truncate=False)" ] }, { "cell_type": "code", "execution_count": 37, "id": "9996788d-19df-41e2-b98c-3f5b5f9e6848", "metadata": {}, "outputs": [], "source": [ "counties_shapefile = \"s3://wherobots-examples/data/examples/natural_earth/ne_10m_admin_2_counties\"" ] }, { "cell_type": "code", "execution_count": 38, "id": "7d8e1ff1-8650-4b98-b9c0-25792d31c77e", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[Stage 45:> (0 + 1) / 1]\r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- geometry: geometry (nullable = true)\n", " |-- FEATURECLA: string (nullable = true)\n", " |-- SCALERANK: string (nullable = true)\n", " |-- ADM2_CODE: string (nullable = true)\n", " |-- ISO_3166_2: string (nullable = true)\n", " |-- ISO_A2: string (nullable = true)\n", " |-- ADM0_SR: string (nullable = true)\n", " |-- NAME: string (nullable = true)\n", " |-- NAME_ALT: string (nullable = true)\n", " |-- NAME_LOCAL: string (nullable = true)\n", " |-- TYPE: string (nullable = true)\n", " |-- TYPE_EN: string (nullable = true)\n", " |-- CODE_LOCAL: string (nullable = true)\n", " |-- REGION: string (nullable = true)\n", " |-- REGION_COD: string (nullable = true)\n", " |-- ABBREV: string (nullable = true)\n", " |-- AREA_SQKM: string (nullable = true)\n", " |-- SAMEASCITY: string (nullable = true)\n", " |-- LABELRANK: string (nullable = true)\n", " |-- NAME_LEN: string (nullable = true)\n", " |-- MAPCOLOR9: string (nullable = true)\n", " |-- MAPCOLOR13: string (nullable = true)\n", " |-- FIPS: string (nullable = true)\n", " |-- SOV_A3: string (nullable = true)\n", " |-- ADM0_A3: string (nullable = true)\n", " |-- ADM0_LABEL: string (nullable = true)\n", " |-- ADMIN: string (nullable = true)\n", " |-- GEONUNIT: string (nullable = true)\n", " |-- GU_A3: string (nullable = true)\n", " |-- MIN_LABEL: string (nullable = true)\n", " |-- MAX_LABEL: string (nullable = true)\n", " |-- MIN_ZOOM: string (nullable = true)\n", " |-- WIKIDATAID: string (nullable = true)\n", " |-- NE_ID: string (nullable = true)\n", " |-- latitude: string (nullable = true)\n", " |-- longitude: string (nullable = true)\n", " |-- NAME_AR: string (nullable = true)\n", " |-- NAME_BN: string (nullable = true)\n", " |-- NAME_DE: string (nullable = true)\n", " |-- NAME_EL: string (nullable = true)\n", " |-- NAME_EN: string (nullable = true)\n", " |-- NAME_ES: string (nullable = true)\n", " |-- NAME_FA: string (nullable = true)\n", " |-- NAME_FR: string (nullable = true)\n", " |-- NAME_HE: string (nullable = true)\n", " |-- NAME_HI: string (nullable = true)\n", " |-- NAME_HU: string (nullable = true)\n", " |-- NAME_ID: string (nullable = true)\n", " |-- NAME_IT: string (nullable = true)\n", " |-- NAME_JA: string (nullable = true)\n", " |-- NAME_KO: string (nullable = true)\n", " |-- NAME_NL: string (nullable = true)\n", " |-- NAME_PL: string (nullable = true)\n", " |-- NAME_PT: string (nullable = true)\n", " |-- NAME_RU: string (nullable = true)\n", " |-- NAME_SV: string (nullable = true)\n", " |-- NAME_TR: string (nullable = true)\n", " |-- NAME_UK: string (nullable = true)\n", " |-- NAME_UR: string (nullable = true)\n", " |-- NAME_VI: string (nullable = true)\n", " |-- NAME_ZH: string (nullable = true)\n", " |-- NAME_ZHT: string (nullable = true)\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "spatialRDD = ShapefileReader.readToGeometryRDD(sedona, counties_shapefile)\n", "counties_df = Adapter.toDf(spatialRDD, sedona)\n", "counties_df.createOrReplaceTempView(\"counties\")\n", "counties_df.printSchema()" ] }, { "cell_type": "code", "execution_count": 39, "id": "8f08611a-1435-4203-b033-89fbace76364", "metadata": {}, "outputs": [], "source": [ "county_light_tiled_df = sedona.sql(\"\"\"\n", "WITH matched_tile AS (\n", " SELECT tile, geometry, FIPS\n", " FROM wherobots.test_db.f10_1993, counties\n", " WHERE RS_Intersects(tile, counties.geometry) \n", ")\n", "\n", "SELECT \n", " sum(RS_ZonalStats(matched_tile.tile, matched_tile.geometry, 'mean')) AS mean_light, \n", " any_value(matched_tile.geometry) AS geometry, \n", " FIPS\n", "FROM matched_tile\n", "GROUP BY FIPS\n", "\"\"\")" ] }, { "cell_type": "code", "execution_count": 40, "id": "51625f63-4a7d-486d-9592-2d55813ff451", "metadata": {}, "outputs": [], "source": [ "county_light_tiled_df.createOrReplaceTempView(\"county_light_1993\")" ] }, { "cell_type": "code", "execution_count": 41, "id": "17e5247b-7d91-43a0-9a8f-75d5680a828d", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[Stage 51:> (0 + 1) / 1]\r" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+--------------------+--------------------+-------+\n", "| mean_light| geometry| FIPS|\n", "+--------------------+--------------------+-------+\n", "| 6.563388510224063|MULTIPOLYGON (((-...|US01003|\n", "| 5.303058346553825|POLYGON ((-85.422...|US01019|\n", "| 7.112594570538514|POLYGON ((-86.413...|US01021|\n", "| 2.5223492723492806|POLYGON ((-88.091...|US01025|\n", "| 9.564617731305812|POLYGON ((-85.789...|US01031|\n", "| 13.433770014555993|POLYGON ((-88.130...|US01033|\n", "| 8.240051020408188|POLYGON ((-86.370...|US01037|\n", "| 2.301078582434537|POLYGON ((-86.191...|US01039|\n", "| 0.9495387954422182|POLYGON ((-86.499...|US01041|\n", "| 8.3112128146453|POLYGON ((-85.770...|US01045|\n", "| 2.008212672420753|POLYGON ((-86.916...|US01047|\n", "| 4.339487179487201|POLYGON ((-86.699...|US01053|\n", "| NaN|POLYGON ((-85.863...|US01071|\n", "| 21.28748280605236|POLYGON ((-87.026...|US01073|\n", "| 2.8376935397757586|POLYGON ((-88.241...|US01075|\n", "| 9.75868121970662|POLYGON ((-87.529...|US01079|\n", "| 12.044760935910418|POLYGON ((-85.083...|US01081|\n", "| 18.568147013782642|POLYGON ((-86.783...|US01089|\n", "| 3.4789029535864975|POLYGON ((-88.195...|US01093|\n", "| 36.043608495696546|POLYGON ((-86.303...|US01095|\n", "| 26.75675321863559|MULTIPOLYGON (((-...|US01097|\n", "| 2.6444855206407305|POLYGON ((-86.907...|US01099|\n", "| 37.593265075573335|POLYGON ((-86.511...|US01101|\n", "| 33.53826026240135|POLYGON ((-86.581...|US01103|\n", "| 1.1684303350969931|POLYGON ((-87.421...|US01105|\n", "| 9.971524463290796|POLYGON ((-88.301...|US01107|\n", "| 13.011129071861175|POLYGON ((-84.998...|US01113|\n", "| 4.809910641754596|POLYGON ((-85.593...|US01123|\n", "| 8.41151685393288|POLYGON ((-87.065...|US01125|\n", "| 1.2630472854640653|POLYGON ((-86.857...|US01131|\n", "| 0.10422005744217205|MULTIPOLYGON (((-...|US02013|\n", "| 0.7744945567651736|POLYGON ((-157.26...|US02060|\n", "| 0.03614775725595106|MULTIPOLYGON (((-...|US02070|\n", "| 4.619017951013784|POLYGON ((-147.00...|US02090|\n", "| 0.03209213910320792|MULTIPOLYGON (((-...|US02100|\n", "|0.029853669307934268|MULTIPOLYGON (((-...|US02105|\n", "| 0.04098077587198586|MULTIPOLYGON (((-...|US02150|\n", "| 0.21807125968592578|MULTIPOLYGON (((-...|US02158|\n", "| 6.29803023696733|MULTIPOLYGON (((-...|US02185|\n", "| 0.1582469415182259|POLYGON ((-164.40...|US02188|\n", "| 0.15516483516485216|MULTIPOLYGON (((-...|US02195|\n", "| 0.10085646780862186|MULTIPOLYGON (((-...|US02220|\n", "|0.037185354691075395|POLYGON ((-135.48...|US02230|\n", "| 0.11782344122055301|MULTIPOLYGON (((-...|US02275|\n", "| 0.24472324900896858|POLYGON ((-141.00...|US02290|\n", "| 2.2717580297073106|POLYGON ((-112.54...|US04005|\n", "| 15.816996835964616|POLYGON ((-111.49...|US04013|\n", "| 1.7759504750453305|POLYGON ((-110.75...|US04017|\n", "| 7.688794802992883|POLYGON ((-111.03...|US04021|\n", "| 1.5279533719292975|POLYGON ((-91.377...|US05001|\n", "| 1.920353982300796|POLYGON ((-91.460...|US05003|\n", "| 10.465916837082402|POLYGON ((-94.563...|US05007|\n", "| 1.010121457489879|POLYGON ((-91.983...|US05011|\n", "| 2.270431427569262|POLYGON ((-93.408...|US05019|\n", "| 2.906217616580315|POLYGON ((-91.837...|US05023|\n", "| 0.529593412249097|POLYGON ((-91.975...|US05025|\n", "| 3.8983805668016687|POLYGON ((-93.238...|US05027|\n", "| 11.952818173441436|POLYGON ((-90.379...|US05031|\n", "| 7.514086802781834|POLYGON ((-90.304...|US05035|\n", "| 1.285983421250936|POLYGON ((-91.457...|US05043|\n", "| 12.884167588875034|POLYGON ((-92.252...|US05045|\n", "| 3.8769922353902655|POLYGON ((-91.793...|US05063|\n", "| 2.9252685660906153|POLYGON ((-91.032...|US05067|\n", "| 1.53237742830715|POLYGON ((-93.709...|US05071|\n", "| 0.780098955470026|POLYGON ((-93.520...|US05073|\n", "| 2.7720979765707727|POLYGON ((-94.407...|US05081|\n", "| 7.235225505443205|POLYGON ((-91.678...|US05085|\n", "| 9.081934846989215|POLYGON ((-94.041...|US05091|\n", "| 6.037962037962009|POLYGON ((-89.723...|US05093|\n", "| 1.860642728913338|POLYGON ((-91.059...|US05095|\n", "| 1.4942065491183798|POLYGON ((-93.373...|US05099|\n", "| 0.7677502138580021|POLYGON ((-93.104...|US05103|\n", "| 5.694871794871785|POLYGON ((-91.036...|US05111|\n", "| 1.8861226371599893|POLYGON ((-91.377...|US05117|\n", "| 1.5684210526316162|POLYGON ((-91.407...|US05121|\n", "| NaN|POLYGON ((-90.502...|US05123|\n", "| 0.8484433800889477|POLYGON ((-94.455...|US05127|\n", "| 14.166481069042172|POLYGON ((-94.450...|US05131|\n", "| 2.064942528735636|POLYGON ((-94.475...|US05133|\n", "| 1.864905660377377|POLYGON ((-92.240...|US05141|\n", "| 4.83930156851134|POLYGON ((-92.111...|US05145|\n", "| 1.1251287332646798|POLYGON ((-91.039...|US05147|\n", "| 1.696002578981324|POLYGON ((-92.927...|US05149|\n", "| 16.7709260687363|POLYGON ((-119.88...|US06003|\n", "| 6.375985412736477|POLYGON ((-120.07...|US06005|\n", "| 2.9443088203897143|POLYGON ((-120.07...|US06009|\n", "| 1.4734786853238142|POLYGON ((-121.88...|US06011|\n", "| 94.27982026143789|POLYGON ((-122.31...|US06013|\n", "| 1.0074585635359046|POLYGON ((-124.06...|US06015|\n", "| 14.33509453996127|POLYGON ((-118.77...|US06019|\n", "| 2.1304226242583373|POLYGON ((-122.00...|US06021|\n", "| 2.01199374477674|POLYGON ((-124.02...|US06023|\n", "| 1.155351130875798|POLYGON ((-115.89...|US06027|\n", "| 83.75094670225657|MULTIPOLYGON (((-...|US06037|\n", "| 6.0181974791927555|POLYGON ((-119.02...|US06039|\n", "| 0.9955249854977457|POLYGON ((-123.53...|US06045|\n", "| 14.513000624831733|POLYGON ((-122.62...|US06055|\n", "| 68.95424107142858|POLYGON ((-120.00...|US06061|\n", "| 1.265862072671394|POLYGON ((-121.07...|US06063|\n", "| 31.23753117206894|POLYGON ((-121.57...|US06067|\n", "+--------------------+--------------------+-------+\n", "only showing top 100 rows\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "county_light_tiled_df.show(100)" ] }, { "cell_type": "code", "execution_count": 42, "id": "7b32981b-6c53-44e3-9cb1-13502baf4a66", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "User Guide: https://docs.kepler.gl/docs/keplergl-jupyter\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/conda/lib/python3.10/site-packages/jupyter_client/session.py:719: UserWarning: Message serialization failed with:\n", "Out of range float values are not JSON compliant\n", "Supporting this message is deprecated in jupyter-client 7, please make sure your message is JSON-compliant\n", " content = self.pack(content)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "903225b7757d4343a02e3232f715f1fa", "version_major": 2, "version_minor": 0 }, "text/plain": [ "KeplerGl(data={'unnamed': {'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "SedonaKepler.create_map(county_light_tiled_df)" ] }, { "cell_type": "code", "execution_count": null, "id": "b0f71dc5-2a2e-499c-8147-e5c2ab7952fb", "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 }