From def803155f8c6f18fe020a27554000d6279bfc6c Mon Sep 17 00:00:00 2001 From: ncclementi Date: Thu, 7 Dec 2023 13:16:30 -0500 Subject: [PATCH] docs(blog-post): add blogpost ibis duckdb geospatial ci(deps): remove lonboard from min versions ci jobs ci(deps): remove lonboard from pyspark ci job --- .github/workflows/ibis-backends.yml | 8 + docs/posts/ibis-duckdb-geospatial/index.qmd | 246 +++++++++ poetry.lock | 562 +++++++++++++++++++- pyproject.toml | 2 + requirements-dev.txt | 31 ++ 5 files changed, 841 insertions(+), 8 deletions(-) create mode 100644 docs/posts/ibis-duckdb-geospatial/index.qmd diff --git a/.github/workflows/ibis-backends.yml b/.github/workflows/ibis-backends.yml index 7527997d8b34..2017fd831bb3 100644 --- a/.github/workflows/ibis-backends.yml +++ b/.github/workflows/ibis-backends.yml @@ -485,6 +485,10 @@ jobs: - name: install poetry run: python -m pip install --upgrade pip 'poetry==1.7.1' + - name: remove lonboard + # it requires a version of pandas that min versions are not compatible with + run: poetry remove lonboard + - name: install minimum versions run: poetry add --lock --optional ${{ join(matrix.backend.deps, ' ') }} @@ -552,6 +556,10 @@ jobs: - name: install poetry run: python -m pip install --upgrade pip 'poetry==1.7.1' + - name: remove lonboard + # it requires a version of pandas that pyspark is not compatible with + run: poetry remove lonboard + - name: install maximum versions of pandas and numpy run: poetry add --lock 'pandas@<2' 'numpy<1.24' diff --git a/docs/posts/ibis-duckdb-geospatial/index.qmd b/docs/posts/ibis-duckdb-geospatial/index.qmd new file mode 100644 index 000000000000..bc768c6beece --- /dev/null +++ b/docs/posts/ibis-duckdb-geospatial/index.qmd @@ -0,0 +1,246 @@ +--- +title: "Ibis + DuckDB geospatial: a match made on Earth" +author: Naty Clementi +date: 2023-12-07 +categories: + - blog + - duckdb + - geospatial +--- + +Ibis now has support for [DuckDB geospatial functions](https://gist.github.com/ncclementi/fbc5564af709e2d7f8882821e3a8649f)! + +This blogpost showcases some examples of the geospatial API for the DuckDB backend. The material is inspired by +the ["DuckDB: Spatial Relationships"](https://geog-414.gishub.org/book/duckdb/07_spatial_relationships.html) lesson from +[Dr. Qiusheng Wu](https://geog-414.gishub.org/book/preface/instructor.html)'s course "Spatial Data Management" from the +Department of Geography & Sustainability at the University of Tennessee, Knoxville. + +::: {.callout-note} +You can check Dr. Qiusheng Wu's full Spatial Data Management course material on its +[website](https://geog-414.gishub.org/index.html), and the classes are also on +[YouTube](https://www.youtube.com/watch?v=A4TOAdsXsEs&list=PLAxJ4-o7ZoPe9SkgnophygyLjTDBzIEbi). +::: + +## Data + +We are going to be working with data from New York City. The database contains multiple tables with information about +subway stations, streets, neighborhood, census data and, homicides. The datasets in the database are in NAD83 / UTM zone +18N projection, EPSG:26918. + +```{python} +from pathlib import Path +from zipfile import ZipFile +from urllib.request import urlretrieve + +# Download and unzip +url = "https://open.gishub.org/data/duckdb/nyc_data.db.zip" +zip_path = Path("nyc_data.db.zip") +db_path = Path("nyc_data.db") + +if not zip_path.exists(): + urlretrieve(url, zip_path) + +if not db_path.exists(): + with ZipFile(zip_path) as zip_file: + zip_file.extract("nyc_data.db") +``` + +## Let's get started + +The beauty of spatial databases is that they allow us to both store *and* compute over geometries. + +```{python} +import ibis +from ibis import _ + +ibis.options.interactive = True + +con = ibis.duckdb.connect("nyc_data.db") +con.list_tables() +``` + +We have multiple tables with information about New York City. Following Dr. Wu's class, we'll take a look at some +spatial relations. + +We can start by taking a peak at the `nyc_subway_stations` table. + +```{python} +subway_stations = con.table("nyc_subway_stations") +subway_stations +``` + +Notice that the last column has a `geometry` type, and in this case it contains points that represent the location of +each subway station. Let's grab the entry for the Broad St subway station. + +```{python} +broad_station = subway_stations.filter(subway_stations.NAME == "Broad St") +broad_station +``` + +### `geo_equals` (`ST_Equals`) + +In DuckDB `ST_Equals` returns `True` if two geometries are topologically equal. This means that they have the same +dimension and identical coordinate values, although the order of the vertices may be different. + +The following is a bit redundant but we can check if our `"Broad St"` point matches only one point in our data using +`geo_equals` + +```{python} +subway_stations.filter(subway_stations.geom.geo_equals(broad_station.geom)) +``` + +We can also write this query without using `broad_station` as a variable, and with the help of the deferred expressions +API, also known as [the underscore API](../../how-to/analytics/chain_expressions.qmd). + +```{python} +subway_stations.filter(_.geom.geo_equals(_.filter(_.NAME == "Broad St").geom)) +``` + +### `intersect` (ST_Intersect) + +Let's locate the neighborhood of the "Broad Street" subway station using the +geospatial `intersect` function. The `intersect` function returns `True` if two geometries have any points in common. + +```{python} +boroughs = con.table("nyc_neighborhoods") +boroughs +``` + +```{python} +boroughs.filter(boroughs.geom.intersects(broad_station.select(broad_station.geom).to_array())) +``` + +### `d_within` (ST_DWithin) + +We can also find the streets near (say, within 10 meters) the Broad St subway station using the `d_within` +function. The `d_within` function returns True if the geometries are within a given distance. + +```{python} +streets = con.table("nyc_streets") +streets +``` + +Using the deferred API, we can check which streets are within `d=10` meters of distance. + +```{python} +sts_near_broad = streets.filter(_.geom.d_within(broad_station.select(_.geom).to_array(), 10)) +sts_near_broad +``` + +::: {.callout-note} +In the previous query, `streets` and `broad_station` are different tables. We use [`to_array()`](../../reference/expression-tables.qmd#ibis.expr.types.relations.Table.to_array) to generate a +scalar subquery from a table with a single column (whose shape is scalar). +::: + +To visualize the findings, we will convert the tables to Geopandas DataFrames. + +```{python} +broad_station_gdf = broad_station.to_pandas() +broad_station_gdf.crs = "EPSG:26918" + +sts_near_broad_gdf = sts_near_broad.to_pandas() +sts_near_broad_gdf.crs = "EPSG:26918" + +streets_gdf = streets.to_pandas() +streets_gdf.crs = "EPSG:26918" +``` + +```{python} +import leafmap.deckgl as leafmap # <1> +``` + +1. `leafmap.deckgl` allows us to visualize multiple layers + +```{python} +m = leafmap.Map() + +m.add_vector(broad_station_gdf, get_fill_color="blue") +m.add_vector(sts_near_broad_gdf, get_color="red", opacity=0.5) +m.add_vector(streets_gdf, get_color="grey", zoom_to_layer=False, opacity=0.3) +m +``` + +You can zoom in and out, and hover over the map to check on the streets names. + +### `buffer` (ST_Buffer) + +Next, we'll take a look at the homicides table and showcase some +additional functionality related to polygon handling. + +```{python} +homicides = con.table("nyc_homicides") +homicides +``` + +Let's use the `buffer` method to find homicides near our `"Broad St"` station point. + +The `buffer` method computes a polygon or multipolygon that represents all points whose distance from a geometry is less +than or equal to a given distance. + +```{python} +broad_station.geom.buffer(200) +``` + +We can check the area using the `area` (`ST_Area`) function, and see that is $~ \pi r^{2}=125664$ + +```{python} +broad_station.geom.buffer(200).area() +``` + +To find if there were any homicides in that area, we can find where the polygon resulting from adding the +200 meters buffer to our "Broad St" station point intersects with the geometry column in our homicides table. + +```{python} +h_near_broad = homicides.filter(_.geom.intersects(broad_station.select(_.geom.buffer(200)).to_array())) +h_near_broad +``` + +It looks like there was one homicide within 200 meters from the "Broad St" station, but from this +data we can't tell the street near which it happened. However, we can check if the homicide point is within a small +distance of a street. + +```{python} +h_street = streets.filter(_.geom.d_within(h_near_broad.select(_.geom).to_array(), 2)) +h_street +``` + +Let's plot this: + +```{python} +broad_station_zone = broad_station.mutate(geom=broad_station.geom.buffer(200)) +broad_station_zone = broad_station_zone.to_pandas() +broad_station_zone.crs = "EPSG:26918" + +h_near_broad_gdf = h_near_broad.to_pandas() +h_near_broad_gdf.crs = "EPSG:26918" + +h_street_gdf = h_street.to_pandas() +h_street_gdf.crs = "EPSG:26918" + + +mh = leafmap.Map() +mh.add_vector(broad_station_gdf, get_fill_color="orange") +mh.add_vector(broad_station_zone, get_fill_color="orange", opacity=0.1) +mh.add_vector(h_near_broad_gdf, get_fill_color="red", opacity=0.5) +mh.add_vector(h_street_gdf, get_color="blue", opacity=0.3) +mh.add_vector(streets_gdf, get_color="grey", zoom_to_layer=False, opacity=0.2) + +mh +``` + + +## Functions supported and next steps + +At the moment in Ibis we have support for around thirty geospatial functions for the DuckDB and we will add some more +(see list [here](https://gist.github.com/ncclementi/fbc5564af709e2d7f8882821e3a8649f)). + +We also support reading multiple geospatial formats via [`read_geo()`](../../backends/duckdb.qmd#ibis.backends.duckdb.Backend.read_geo). + +Here are some resources to learn more about Ibis: + +- [Ibis Docs](https://ibis-project.org/) +- [Ibis GitHub](https://github.com/ibis-project/ibis) + +Chat with us on Zulip: + +- [Ibis Zulip Chat](https://ibis-project.zulipchat.com/) diff --git a/poetry.lock b/poetry.lock index b9fd81b9e918..d03c910f11b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -145,6 +145,26 @@ files = [ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, ] +[[package]] +name = "anywidget" +version = "0.7.1" +description = "custom jupyter widgets made easy" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anywidget-0.7.1-py3-none-any.whl", hash = "sha256:17828c6e255a7066c960636cbda045d55b08c996a2fc4e886e4c8507db6e9407"}, + {file = "anywidget-0.7.1.tar.gz", hash = "sha256:1c4cb51063f8ec5172b8c8efb1bfb79861d340c3491220d56b8c2a6aa8db3b3d"}, +] + +[package.dependencies] +ipywidgets = ">=7.6.0" +psygnal = ">=0.8.1" +typing-extensions = ">=4.2.0" + +[package.extras] +dev = ["comm (>=0.1.0)", "watchfiles (>=0.18.0)"] +test = ["black[jupyter]", "ipython (<8.13)", "msgspec", "pydantic", "pytest", "pytest-cov", "ruff"] + [[package]] name = "appdirs" version = "1.4.4" @@ -254,6 +274,24 @@ doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2. test-tox = ["mypy (>=0.800)", "numpy", "pandera", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] test-tox-coverage = ["coverage (>=5.5)"] +[[package]] +name = "beautifulsoup4" +version = "4.12.2" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, + {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "bidict" version = "0.22.1" @@ -461,6 +499,38 @@ pathspec = "*" rich = "*" tomli = "*" +[[package]] +name = "bqplot" +version = "0.12.42" +description = "Interactive plotting for the Jupyter notebook, using d3.js and ipywidgets." +optional = false +python-versions = ">=3.6" +files = [ + {file = "bqplot-0.12.42-py2.py3-none-any.whl", hash = "sha256:f040951f244b89ccf6a3db835e35c641ceee95906eb3bb8c337da14b56471c0c"}, + {file = "bqplot-0.12.42.tar.gz", hash = "sha256:99486f74cabcfdff841dfee41ba6d2b47782d85a34ff36a34a223d43ffc0a729"}, +] + +[package.dependencies] +ipywidgets = ">=7.5.0,<9" +numpy = ">=1.10.4" +pandas = ">=1.0.0,<3.0.0" +traitlets = ">=4.3.0" +traittypes = ">=0.0.6" + +[[package]] +name = "branca" +version = "0.7.0" +description = "Generate complex HTML+JS pages with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "branca-0.7.0-py3-none-any.whl", hash = "sha256:c653d9a3fef1e6cd203757c77d3eb44810f11998506451f9a27d52b983500c16"}, + {file = "branca-0.7.0.tar.gz", hash = "sha256:503ccb589a9ee9464cb7b5b17e5ffd8d5082c5c28624197f58f20d4d377a68bb"}, +] + +[package.dependencies] +jinja2 = "*" + [[package]] name = "build" version = "1.0.3" @@ -746,7 +816,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "click-plugins" version = "1.1.1" description = "An extension module for click to enable registering CLI commands via setuptools entry-points." -optional = true +optional = false python-versions = "*" files = [ {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, @@ -869,7 +939,7 @@ sqlalchemy = ["sqlalchemy (>1.3.21,<2.0)"] name = "cligj" version = "0.7.2" description = "Click params for commmand line interfaces to GeoJSON" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4" files = [ {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"}, @@ -925,6 +995,20 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "colour" +version = "0.1.5" +description = "converts and manipulates various color representation (HSL, RVB, web, X11, ...)" +optional = false +python-versions = "*" +files = [ + {file = "colour-0.1.5-py2.py3-none-any.whl", hash = "sha256:33f6db9d564fadc16e59921a56999b79571160ce09916303d35346dddc17978c"}, + {file = "colour-0.1.5.tar.gz", hash = "sha256:af20120fefd2afede8b001fbef2ea9da70ad7d49fafdb6489025dae8745c3aee"}, +] + +[package.extras] +test = ["nose"] + [[package]] name = "comm" version = "0.2.0" @@ -1314,7 +1398,7 @@ zict = ">=3.0.0" name = "duckdb" version = "0.9.2" description = "DuckDB embedded database" -optional = true +optional = false python-versions = ">=3.7.0" files = [ {file = "duckdb-0.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aadcea5160c586704c03a8a796c06a8afffbefefb1986601104a60cb0bfdb5ab"}, @@ -1550,7 +1634,7 @@ typing = ["typing-extensions (>=4.8)"] name = "fiona" version = "1.9.5" description = "Fiona reads and writes spatial data files" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "fiona-1.9.5-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:5f40a40529ecfca5294260316cf987a0420c77a2f0cf0849f529d1afbccd093e"}, @@ -1595,6 +1679,27 @@ calc = ["shapely"] s3 = ["boto3 (>=1.3.1)"] test = ["Fiona[s3]", "pytest (>=7)", "pytest-cov", "pytz"] +[[package]] +name = "folium" +version = "0.15.1" +description = "Make beautiful maps with Leaflet.js & Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "folium-0.15.1-py2.py3-none-any.whl", hash = "sha256:480f217b80d27530eef22e0535030f1696d61a2d55e6cc17acc36750cca89463"}, + {file = "folium-0.15.1.tar.gz", hash = "sha256:cb792d11e8049a455d3dc6416cdd8e7a1623d6b949f6e42c45a5d8fa4d1e24f4"}, +] + +[package.dependencies] +branca = ">=0.6.0" +jinja2 = ">=2.9" +numpy = "*" +requests = "*" +xyzservices = "*" + +[package.extras] +testing = ["pytest"] + [[package]] name = "fonttools" version = "4.46.0" @@ -1789,6 +1894,24 @@ requests = "*" crc = ["crcmod"] gcsfuse = ["fusepy"] +[[package]] +name = "gdown" +version = "4.7.1" +description = "Google Drive direct download of big files." +optional = false +python-versions = "*" +files = [ + {file = "gdown-4.7.1-py3-none-any.whl", hash = "sha256:65d495699e7c2c61af0d0e9c32748fb4f79abaf80d747a87456c7be14aac2560"}, + {file = "gdown-4.7.1.tar.gz", hash = "sha256:347f23769679aaf7efa73e5655270fcda8ca56be65eb84a4a21d143989541045"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +filelock = "*" +requests = {version = "*", extras = ["socks"]} +six = "*" +tqdm = "*" + [[package]] name = "geoalchemy2" version = "0.14.2" @@ -1807,11 +1930,22 @@ SQLAlchemy = ">=1.4" [package.extras] shapely = ["Shapely (>=1.7)"] +[[package]] +name = "geojson" +version = "3.1.0" +description = "Python bindings and utilities for GeoJSON" +optional = false +python-versions = ">=3.7" +files = [ + {file = "geojson-3.1.0-py3-none-any.whl", hash = "sha256:68a9771827237adb8c0c71f8527509c8f5bef61733aa434cefc9c9d4f0ebe8f3"}, + {file = "geojson-3.1.0.tar.gz", hash = "sha256:58a7fa40727ea058efc28b0e9ff0099eadf6d0965e04690830208d3ef571adac"}, +] + [[package]] name = "geopandas" version = "0.14.1" description = "Geographic pandas extensions" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "geopandas-0.14.1-py3-none-any.whl", hash = "sha256:ed5a7cae7874bfc3238fb05e0501cc1760e1b7b11e5b76ecad29da644ca305da"}, @@ -2443,6 +2577,38 @@ files = [ {file = "installer-0.7.0.tar.gz", hash = "sha256:a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631"}, ] +[[package]] +name = "ipyevents" +version = "2.0.2" +description = "A custom widget for returning mouse and keyboard events to Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "ipyevents-2.0.2-py3-none-any.whl", hash = "sha256:60c2a9e992bdc41e8577aa27e57b124efafa48a59a3bff886029fe5700d546b3"}, + {file = "ipyevents-2.0.2.tar.gz", hash = "sha256:26e878b0c5854bc8b6bd6a2bd2c89b314ebe86fda642f4d2434051545bab258f"}, +] + +[package.dependencies] +ipywidgets = ">=7.6.0" + +[package.extras] +docs = ["jupyterlab (>=3)", "nbsphinx", "sphinx"] +test = ["nbval", "pytest", "pytest-cov"] + +[[package]] +name = "ipyfilechooser" +version = "0.6.0" +description = "Python file chooser widget for use in Jupyter/IPython in conjunction with ipywidgets" +optional = false +python-versions = "*" +files = [ + {file = "ipyfilechooser-0.6.0-py3-none-any.whl", hash = "sha256:4555c24b30b819c91dc0ae5e6f7e4cf8f90e5cca531a9209a1fe4deee288d5c5"}, + {file = "ipyfilechooser-0.6.0.tar.gz", hash = "sha256:41df9e4395a924f8e1b78e2804dbe5066dc3fdc233fb07fecfcdc2a0c9a7d8d3"}, +] + +[package.dependencies] +ipywidgets = "*" + [[package]] name = "ipykernel" version = "6.27.1" @@ -2476,6 +2642,23 @@ pyqt5 = ["pyqt5"] pyside6 = ["pyside6"] test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] +[[package]] +name = "ipyleaflet" +version = "0.18.0" +description = "A Jupyter widget for dynamic Leaflet maps" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ipyleaflet-0.18.0-py3-none-any.whl", hash = "sha256:b79b367d971e9b8c296650c9f7fe4b02e99fa709af5f0c81a63f80dd6c6bb475"}, + {file = "ipyleaflet-0.18.0.tar.gz", hash = "sha256:ece484a39282dbb40db96f4963e8f531d0362cbc5131aa9d2c488e962418184f"}, +] + +[package.dependencies] +branca = ">=0.5.0" +ipywidgets = ">=7.6.0,<9" +traittypes = ">=0.2.1,<3" +xyzservices = ">=2021.8.1" + [[package]] name = "ipython" version = "8.18.1" @@ -2513,6 +2696,41 @@ qtconsole = ["qtconsole"] test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] +[[package]] +name = "ipytree" +version = "0.2.2" +description = "A Tree Widget using jsTree" +optional = false +python-versions = "*" +files = [ + {file = "ipytree-0.2.2-py2.py3-none-any.whl", hash = "sha256:744dc1a02c3ec26df8a5ecd87d085a67dc8232a1def6048834403ddcf3b64143"}, + {file = "ipytree-0.2.2.tar.gz", hash = "sha256:d53d739bbaaa45415733cd06e0dc420a2af3d173438617db472a517bc7a61e56"}, +] + +[package.dependencies] +ipywidgets = ">=7.5.0,<9" + +[[package]] +name = "ipywidgets" +version = "8.1.1" +description = "Jupyter interactive widgets" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ipywidgets-8.1.1-py3-none-any.whl", hash = "sha256:2b88d728656aea3bbfd05d32c747cfd0078f9d7e159cf982433b58ad717eed7f"}, + {file = "ipywidgets-8.1.1.tar.gz", hash = "sha256:40211efb556adec6fa450ccc2a77d59ca44a060f4f9f136833df59c9f538e6e8"}, +] + +[package.dependencies] +comm = ">=0.1.3" +ipython = ">=6.1.0" +jupyterlab-widgets = ">=3.0.9,<3.1.0" +traitlets = ">=4.3.1" +widgetsnbextension = ">=4.0.9,<4.1.0" + +[package.extras] +test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] + [[package]] name = "jaraco-classes" version = "3.3.0" @@ -2670,6 +2888,17 @@ traitlets = ">=5.3" docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "jupyterlab-widgets" +version = "3.0.9" +description = "Jupyter interactive widgets for JupyterLab" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyterlab_widgets-3.0.9-py3-none-any.whl", hash = "sha256:3cf5bdf5b897bf3bccf1c11873aa4afd776d7430200f765e0686bd352487b58d"}, + {file = "jupyterlab_widgets-3.0.9.tar.gz", hash = "sha256:6005a4e974c7beee84060fdfba341a3218495046de8ae3ec64888e5fe19fdb4c"}, +] + [[package]] name = "keyring" version = "24.3.0" @@ -2806,6 +3035,50 @@ files = [ {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] +[[package]] +name = "leafmap" +version = "0.29.6" +description = "A Python package for geospatial analysis and interactive mapping in a Jupyter environment." +optional = false +python-versions = ">=3.8" +files = [ + {file = "leafmap-0.29.6-py2.py3-none-any.whl", hash = "sha256:d9da588a271e18771fba042451028f2bc95e920e0067d4a58d1dfdbb80c600d2"}, + {file = "leafmap-0.29.6.tar.gz", hash = "sha256:7a76849f92cdec09417872a14275a456185b64d6321283e09caebb77d6989e48"}, +] + +[package.dependencies] +bqplot = "*" +colour = "*" +duckdb = "*" +folium = "*" +gdown = "*" +geojson = "*" +ipyevents = "*" +ipyfilechooser = "*" +ipyleaflet = "*" +ipywidgets = "*" +matplotlib = "*" +numpy = "*" +pandas = "*" +plotly = "*" +pyshp = "*" +pystac-client = "*" +python-box = "*" +scooby = "*" +whiteboxgui = "*" +xyzservices = "*" + +[package.extras] +ai = ["geopandas", "localtileserver", "osmnx", "pytorch-lightning", "rastervision"] +all = ["PyYAML (==6.0.1)", "black", "black[jupyter]", "bokeh", "boto3", "codespell", "cogeo-mosaic", "deadlink", "ffmpeg-python", "geopandas", "googledrivedownloader", "gradio", "h5py", "ipygany", "ipysheet", "ipyvtklink", "jupyter-bokeh", "jupyterlab (>=3.0.0)", "keplergl", "laspy", "localtileserver", "lonboard", "mapclassify (>=2.4.0)", "mss", "netcdf4", "osmnx", "owslib", "palettable", "panel", "plotly", "pmtiles", "psycopg2", "pycrs", "pydeck", "pyntcloud[las]", "pyvista-xarray", "rasterio", "rasterstats", "rio-cogeo", "rioxarray", "sqlalchemy", "streamlit-folium", "xarray-leaflet"] +apps = ["solara", "streamlit-folium", "voila"] +backends = ["bokeh", "keplergl", "plotly", "pydeck"] +lidar = ["ipygany", "ipyvtklink", "laspy", "panel", "pyntcloud[las]", "pyvista"] +pmtiles = ["flask", "flask-cors", "pmtiles"] +raster = ["jupyter-server-proxy", "localtileserver", "netcdf4", "py3dep", "pynhd", "rio-cogeo", "rioxarray"] +sql = ["psycopg2", "sqlalchemy"] +vector = ["flask", "flask-cors", "geopandas", "lonboard", "mapclassify", "osmnx", "pmtiles"] + [[package]] name = "locket" version = "1.0.0" @@ -2817,6 +3090,26 @@ files = [ {file = "locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632"}, ] +[[package]] +name = "lonboard" +version = "0.5.0" +description = "Python library for fast, interactive geospatial vector data visualization in Jupyter." +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "lonboard-0.5.0-py3-none-any.whl", hash = "sha256:f62590c5a2562cc21653253d0a167dcbd2e0f2d3a72a6344e112c0f959e7feee"}, + {file = "lonboard-0.5.0.tar.gz", hash = "sha256:70d7d347a3175c53a257175f381072cc633e4cb058534aaff6a5725c22cd0095"}, +] + +[package.dependencies] +anywidget = ">=0.7.1,<0.8.0" +geopandas = ">=0.13" +matplotlib = ">=3.7,<4.0" +palettable = ">=3.3.3,<4.0.0" +pandas = ">=2,<3" +pyarrow = ">=14.0.1" +shapely = ">=2,<3" + [[package]] name = "lz4" version = "4.3.2" @@ -3424,6 +3717,17 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "palettable" +version = "3.3.3" +description = "Color palettes for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "palettable-3.3.3-py2.py3-none-any.whl", hash = "sha256:74e9e7d7fe5a9be065e02397558ed1777b2df0b793a6f4ce1a5ee74f74fb0caa"}, + {file = "palettable-3.3.3.tar.gz", hash = "sha256:094dd7d9a5fc1cca4854773e5c1fc6a315b33bd5b3a8f47064928facaf0490a8"}, +] + [[package]] name = "pandas" version = "2.1.4" @@ -4031,6 +4335,53 @@ files = [ {file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, ] +[[package]] +name = "psygnal" +version = "0.9.5" +description = "Fast python callback/event system modeled after Qt Signals" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psygnal-0.9.5-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:54a55f5193c070f683542c373028084c0a1f8fa247f4500c66a01b17f96f4314"}, + {file = "psygnal-0.9.5-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:b9f6b5cea9b11fd14ed1ac78eef33c4332aebc4862736883960e7e513404b7ba"}, + {file = "psygnal-0.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a3ff86f5c20469419e67a00ad913d619afe10a488e2abbb9fff8683f11bbaef"}, + {file = "psygnal-0.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:39890829750905553776160746a9433ed6c7b9cdf4064b7d5e1d958b808b37d7"}, + {file = "psygnal-0.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:43160c91eef076d83f25fdf38460ad23c6f78a2740988eee335b50aeea566ac2"}, + {file = "psygnal-0.9.5-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:5412575ea2db2b0aa783463185cb10d1ccd227fbc29fd971aabacca1fa97113e"}, + {file = "psygnal-0.9.5-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:6d41e16a19e98b79431c33183611e961ecc74610987249e52bae097774f3aa71"}, + {file = "psygnal-0.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05cc3b4b253ea6d8efda736de89a6174c1b958a359f78a7842b8049fdfe4ef74"}, + {file = "psygnal-0.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d332a874263951e0a0158e3cef82601bce8e1cfe6f4c57a8d20d02f942e8bdb4"}, + {file = "psygnal-0.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:21132b6ae5a7cfc8b2078b24cc3d7dc59fd07d867f649e10ef092976c4b8e33f"}, + {file = "psygnal-0.9.5-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:a379aaf7b6e4caf107851c5d948694ddf3e1ce4ca83a16ccd0dceee870e2d5f0"}, + {file = "psygnal-0.9.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2338ea6e3a952a93a1b524e674ae1176666c0cd887311d8e93716e19f05a9da7"}, + {file = "psygnal-0.9.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db88899c1da064e54fbac9fdb49fa34e73d762918fdb6c541c9f90fb6c232161"}, + {file = "psygnal-0.9.5-cp37-cp37m-win_amd64.whl", hash = "sha256:b5b575dd9b8a8b221104ca51ebc44bc7b06f2425991401690c46633befec2721"}, + {file = "psygnal-0.9.5-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:06b79289705888199d63bfa0579be85b15df7df578c27d2bb54f0f51e7faec44"}, + {file = "psygnal-0.9.5-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:bf0d0c9bea1f8c3d379ae6ac52d87c52b4fe62a651db2f06e92b964fb7bc2539"}, + {file = "psygnal-0.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8fa4929a66ba776d98f119db8d87f144d102c86c4ee9893a427507bde46d704"}, + {file = "psygnal-0.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9b6e1249240177ff1bfc7dd19df983bdaba0a59361613ff9138b8f0349787d9c"}, + {file = "psygnal-0.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:e2f0623a1cbb40791e6e6787f6859fad52e65241d34f516caaf9968663d5405b"}, + {file = "psygnal-0.9.5-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:ef576ba8dde2b2b5f786a37bdfce3b4608047c69c55653be071855c32f012f99"}, + {file = "psygnal-0.9.5-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:407ee58cac4b683f58cf0ccae21ad8c0371aff4cb6b55f531ff61aca73fdcf0e"}, + {file = "psygnal-0.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42d6168e891050005c7b7474897c35188b7be7f62bb88efe93985d6c6a50a9c3"}, + {file = "psygnal-0.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb85ed3e8d22d97d98f86af714eec0a3458a659bf72296423036acc7acaa29ec"}, + {file = "psygnal-0.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:f511de71282598c30f4a0ce268300d384dc8d4dd536ceb0e4b47759558931282"}, + {file = "psygnal-0.9.5-py3-none-any.whl", hash = "sha256:13b3db8cbf0eea620abd6b611912087ffb23621c8bad20d90b037cc57c3985d5"}, + {file = "psygnal-0.9.5.tar.gz", hash = "sha256:4956ea6c36a75f7fc457558935b67dd8be2594661b4d08eeb3357d69c509c55f"}, +] + +[package.dependencies] +mypy-extensions = "*" +typing-extensions = ">=3.7.4.2" + +[package.extras] +dev = ["black", "cruft", "dask", "ipython", "mypy", "numpy", "pre-commit", "pydantic", "pyqt5", "pytest", "pytest-cov", "pytest-mypy-plugins", "pytest-qt", "qtpy", "rich", "ruff", "wrapt"] +docs = ["griffe (==0.25.5)", "mkdocs (==1.4.2)", "mkdocs-material (==8.5.10)", "mkdocs-minify-plugin", "mkdocs-spellcheck[all]", "mkdocstrings (==0.20.0)", "mkdocstrings-python (==0.8.3)"] +proxy = ["wrapt"] +pydantic = ["pydantic"] +test = ["attrs", "dask", "msgspec", "numpy", "pydantic", "pyinstaller (>=4.0)", "pytest (>=6.0)", "pytest-codspeed", "pytest-cov", "toolz", "wrapt"] +testqt = ["pytest-qt", "qtpy"] + [[package]] name = "ptyprocess" version = "0.7.0" @@ -4609,7 +4960,7 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pyproj" version = "3.6.1" description = "Python interface to PROJ (cartographic projections and coordinate transformations library)" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "pyproj-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4"}, @@ -4658,6 +5009,29 @@ files = [ [package.dependencies] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +[[package]] +name = "pyshp" +version = "2.3.1" +description = "Pure Python read/write support for ESRI Shapefile format" +optional = false +python-versions = ">=2.7" +files = [ + {file = "pyshp-2.3.1-py2.py3-none-any.whl", hash = "sha256:67024c0ccdc352ba5db777c4e968483782dfa78f8e200672a90d2d30fd8b7b49"}, + {file = "pyshp-2.3.1.tar.gz", hash = "sha256:4caec82fd8dd096feba8217858068bacb2a3b5950f43c048c6dc32a3489d5af1"}, +] + +[[package]] +name = "pysocks" +version = "1.7.1" +description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, + {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, + {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, +] + [[package]] name = "pyspark" version = "3.3.3" @@ -4677,6 +5051,50 @@ mllib = ["numpy (>=1.15)"] pandas-on-spark = ["numpy (>=1.15)", "pandas (>=1.0.5)", "pyarrow (>=1.0.0)"] sql = ["pandas (>=1.0.5)", "pyarrow (>=1.0.0)"] +[[package]] +name = "pystac" +version = "1.9.0" +description = "Python library for working with the SpatioTemporal Asset Catalog (STAC) specification" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pystac-1.9.0-py3-none-any.whl", hash = "sha256:64d5654166290169ad6ad2bc0d5337a1664ede1165635f0b73b327065b801a2f"}, + {file = "pystac-1.9.0.tar.gz", hash = "sha256:c6b5a86e241fca5e9267a7902c26679f208749a107e9015fe6aaf73a9dd40948"}, +] + +[package.dependencies] +jsonschema = {version = ">=4.18,<5.0", optional = true, markers = "extra == \"validation\""} +python-dateutil = ">=2.7.0" + +[package.extras] +bench = ["asv (>=0.6.0,<0.7.0)", "packaging (>=23.1,<24.0)", "virtualenv (>=20.22,<21.0)"] +docs = ["Sphinx (>=6.2,<7.0)", "boto3 (>=1.28,<2.0)", "ipython (>=8.12,<9.0)", "jinja2 (<4.0)", "jupyter (>=1.0,<2.0)", "nbsphinx (>=0.9.0,<0.10.0)", "pydata-sphinx-theme (>=0.13,<1.0)", "rasterio (>=1.3,<2.0)", "shapely (>=2.0,<3.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-design (>=0.5.0,<0.6.0)", "sphinxcontrib-fulltoc (>=1.2,<2.0)"] +jinja2 = ["jinja2 (<4.0)"] +orjson = ["orjson (>=3.5)"] +test = ["black (>=23.3,<24.0)", "codespell (>=2.2,<3.0)", "coverage (>=7.2,<8.0)", "doc8 (>=1.1,<2.0)", "html5lib (>=1.1,<2.0)", "jinja2 (<4.0)", "jsonschema (>=4.18,<5.0)", "mypy (>=1.2,<2.0)", "orjson (>=3.8,<4.0)", "pre-commit (>=3.2,<4.0)", "pytest (>=7.3,<8.0)", "pytest-cov (>=4.0,<5.0)", "pytest-mock (>=3.10,<4.0)", "pytest-recording (>=0.13.0,<0.14.0)", "requests-mock (>=1.11,<2.0)", "ruff (==0.1.1)", "types-html5lib (>=1.1,<2.0)", "types-jsonschema (>=4.18,<5.0)", "types-orjson (>=3.6,<4.0)", "types-python-dateutil (>=2.8,<3.0)", "types-urllib3 (>=1.26,<2.0)"] +urllib3 = ["urllib3 (>=1.26)"] +validation = ["jsonschema (>=4.18,<5.0)"] + +[[package]] +name = "pystac-client" +version = "0.7.5" +description = "Python library for working with SpatioTemporal Asset Catalog (STAC) APIs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pystac-client-0.7.5.tar.gz", hash = "sha256:4b0ed0f7177dfc6e394aeb3ecf1236364f315b1d38c107afbcbbef17c2f7db8b"}, + {file = "pystac_client-0.7.5-py3-none-any.whl", hash = "sha256:b07c21f0bfbe7ea19cd23e535406ee08ee604b8ff8d9afcee666c0b1fe017dc4"}, +] + +[package.dependencies] +pystac = {version = ">=1.8.2", extras = ["validation"]} +python-dateutil = ">=2.8.2" +requests = ">=2.28.2" + +[package.extras] +dev = ["black (>=23.3,<24.0)", "codespell (>=2.2.4,<2.3.0)", "coverage (>=7.2,<8.0)", "doc8 (>=1.1.1,<1.2.0)", "importlib-metadata (>=6.7,<7.0)", "mypy (>=1.2,<2.0)", "orjson (>=3.8,<4.0)", "pre-commit (>=3.2,<4.0)", "pytest (>=7.4,<8.0)", "pytest-benchmark (>=4.0.0,<4.1.0)", "pytest-console-scripts (>=1.4.0,<1.5.0)", "pytest-cov (>=4.1.0,<4.2.0)", "pytest-recording (>=0.13,<1.0)", "recommonmark (>=0.7.1,<0.8.0)", "requests-mock (>=1.11.0,<1.12.0)", "ruff (==0.0.287)", "tomli (>=2.0,<3.0)", "types-python-dateutil (>=2.8.19,<2.9.0)", "types-requests (>=2.31.0,<2.32.0)", "urllib3 (<2)"] +docs = ["Sphinx (>=6.2,<7.0)", "boto3 (>=1.26,<2.0)", "cartopy (>=0.21,<1.0)", "geojson (>=3.0.1,<3.1.0)", "geopandas (>=0.13.0,<0.14.0)", "geoviews (>=1.9,<2.0)", "hvplot (>=0.8.3,<0.9.0)", "ipykernel (>=6.22,<7.0)", "ipython (>=8.12,<9.0)", "jinja2 (<4.0)", "matplotlib (>=3.7.1,<3.8.0)", "myst-parser (>=2.0,<3.0)", "nbsphinx (>=0.9,<1.0)", "pydata-sphinx-theme (>=0.13,<1.0)", "pygeoif (>=1.0,<2.0)", "scipy (>=1.10,<2.0)", "sphinxcontrib-fulltoc (>=1.2,<2.0)"] + [[package]] name = "pytest" version = "7.4.3" @@ -4846,6 +5264,38 @@ psutil = ["psutil (>=3.0)"] setproctitle = ["setproctitle"] testing = ["filelock"] +[[package]] +name = "python-box" +version = "7.1.1" +description = "Advanced Python dictionaries with dot notation access" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-box-7.1.1.tar.gz", hash = "sha256:2a3df244a5a79ac8f8447b5d11b5be0f2747d7b141cb2866060081ae9b53cc50"}, + {file = "python_box-7.1.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:81ed1ec0f0ff2370227fc07277c5baca46d190a4747631bad7eb6ab1630fb7d9"}, + {file = "python_box-7.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8891735b4148e84d348c6eadd2f127152f751c9603e35d43a1f496183a291ac4"}, + {file = "python_box-7.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:0036fd47d388deaca8ebd65aea905f88ee6ef91d1d8ce34898b66f1824afbe80"}, + {file = "python_box-7.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aabf8b9ae5dbc8ba431d8cbe0d4cfe737a25d52d68b0f5f2ff34915c21a2c1db"}, + {file = "python_box-7.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c046608337e723ae4de3206db5d1e1202ed166da2dfdc70c1f9361e72ace5633"}, + {file = "python_box-7.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:f9266795e9c233874fb5b34fa994054b4fb0371881678e6ec45aec17fc95feac"}, + {file = "python_box-7.1.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:f76b5b7f0cdc07bfdd4200dc24e6e33189bb2ae322137a2b7110fd41891a3157"}, + {file = "python_box-7.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ea13c98e05a3ec0ff26f254986a17290b69b5ade209fad081fd628f8fcfaa08"}, + {file = "python_box-7.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3f346e332dba16df0b0543d319d9e7ce07d93e5ae152175302894352aa2d28"}, + {file = "python_box-7.1.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:24c4ec0ee0278f66321100aaa9c615413da27a14ff43d376a2a3b4665e1d9494"}, + {file = "python_box-7.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d95e5eec4fc8f3fc5c9cc7347fc2eb4f9187c853d34c90b1658d1eff96cd4eac"}, + {file = "python_box-7.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:a0f1333c42e81529b6f68c192050df9d4505b803be7ac47f114036b98707f7cf"}, + {file = "python_box-7.1.1-py3-none-any.whl", hash = "sha256:63b609555554d7a9d4b6e725f8e78ef1717c67e7d386200e03422ad612338df8"}, +] + +[package.extras] +all = ["msgpack", "ruamel.yaml (>=0.17)", "toml"] +msgpack = ["msgpack"] +pyyaml = ["PyYAML"] +ruamel-yaml = ["ruamel.yaml (>=0.17)"] +toml = ["toml"] +tomli = ["tomli", "tomli-w"] +yaml = ["ruamel.yaml (>=0.17)"] + [[package]] name = "python-dateutil" version = "2.8.2" @@ -5325,6 +5775,7 @@ files = [ certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" +PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7", optional = true, markers = "extra == \"socks\""} urllib3 = ">=1.21.1,<3" [package.extras] @@ -5618,6 +6069,20 @@ dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyl doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "scooby" +version = "0.9.2" +description = "A Great Dane turned Python environment detective" +optional = false +python-versions = ">=3.8" +files = [ + {file = "scooby-0.9.2-py3-none-any.whl", hash = "sha256:3cbc59de9febf8c8ba1e01bc7d08b4eca18ece3212d38b08a6f45188f88c8ea9"}, + {file = "scooby-0.9.2.tar.gz", hash = "sha256:28df643bb7c2087547b2e2220070e2f89e815ddbc515fbc28dd5df2b0a14293e"}, +] + +[package.extras] +cpu = ["mkl", "psutil"] + [[package]] name = "seaborn" version = "0.13.0" @@ -5674,7 +6139,7 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar name = "shapely" version = "2.0.2" description = "Manipulation and analysis of geometric objects" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "shapely-2.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6ca8cffbe84ddde8f52b297b53f8e0687bd31141abb2c373fd8a9f032df415d6"}, @@ -5833,6 +6298,17 @@ files = [ {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "sphobjinv" version = "2.3.1" @@ -6197,6 +6673,23 @@ files = [ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] +[[package]] +name = "traittypes" +version = "0.2.1" +description = "Scipy trait types" +optional = false +python-versions = "*" +files = [ + {file = "traittypes-0.2.1-py2.py3-none-any.whl", hash = "sha256:1340af133810b6eee1a2eb2e988f862b0d12b6c2d16f282aaf3207b782134c2e"}, + {file = "traittypes-0.2.1.tar.gz", hash = "sha256:be6fa26294733e7489822ded4ae25da5b4824a8a7a0e0c2dccfde596e3489bd6"}, +] + +[package.dependencies] +traitlets = ">=4.2.2" + +[package.extras] +test = ["numpy", "pandas", "pytest", "xarray"] + [[package]] name = "trino" version = "0.327.0" @@ -6375,6 +6868,48 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "whitebox" +version = "2.3.1" +description = "An advanced geospatial data analysis platform" +optional = false +python-versions = "*" +files = [ + {file = "whitebox-2.3.1-py2.py3-none-any.whl", hash = "sha256:38becfa894091c0adcebb162ffe7eb8b735e9a52f91376d36cb1a554bd10544d"}, + {file = "whitebox-2.3.1.tar.gz", hash = "sha256:6b4080bc8181f0876cda6c9093bcb463faa4ab8a8c2c631c06b579d3ec1131ba"}, +] + +[package.dependencies] +Click = ">=6.0" + +[[package]] +name = "whiteboxgui" +version = "2.3.0" +description = "An interactive GUI for whitebox-tools in a Jupyter-based environment" +optional = false +python-versions = ">=3.5" +files = [ + {file = "whiteboxgui-2.3.0-py2.py3-none-any.whl", hash = "sha256:f226783efaba1af1cd55f98bba743da590bccf4dd6cbba519f6c879993b57631"}, + {file = "whiteboxgui-2.3.0.tar.gz", hash = "sha256:c59dfccb244bc2d7b9ff77c63a81b77d0e1b4a6fc19476449e450e0da009a754"}, +] + +[package.dependencies] +ipyfilechooser = "*" +ipytree = "*" +ipywidgets = "*" +whitebox = "*" + +[[package]] +name = "widgetsnbextension" +version = "4.0.9" +description = "Jupyter interactive widgets for Jupyter Notebook" +optional = false +python-versions = ">=3.7" +files = [ + {file = "widgetsnbextension-4.0.9-py3-none-any.whl", hash = "sha256:91452ca8445beb805792f206e560c1769284267a30ceb1cec9f5bcc887d15175"}, + {file = "widgetsnbextension-4.0.9.tar.gz", hash = "sha256:3c1f5e46dc1166dfd40a42d685e6a51396fd34ff878742a3e47c6f0cc4a2a385"}, +] + [[package]] name = "xattr" version = "0.10.1" @@ -6576,6 +7111,17 @@ files = [ {file = "xxhash-3.4.1.tar.gz", hash = "sha256:0379d6cf1ff987cd421609a264ce025e74f346e3e145dd106c0cc2e3ec3f99a9"}, ] +[[package]] +name = "xyzservices" +version = "2023.10.1" +description = "Source of XYZ tiles providers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "xyzservices-2023.10.1-py3-none-any.whl", hash = "sha256:6a4c38d3a9f89d3e77153eff9414b36a8ee0850c9e8b85796fd1b2a85b8dfd68"}, + {file = "xyzservices-2023.10.1.tar.gz", hash = "sha256:091229269043bc8258042edbedad4fcb44684b0473ede027b5672ad40dc9fa02"}, +] + [[package]] name = "yarl" version = "1.9.4" @@ -6794,4 +7340,4 @@ visualization = ["graphviz"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "bd26c49dcfdb2afd85fdc872ae0b6dcef24ded442a1c657883630d9cc2e71951" +content-hash = "f1f6deb2b4fc32ca5cf386d9339cb027699bf16c436e6cb754ae8e41091fa2a1" diff --git a/pyproject.toml b/pyproject.toml index 292301c81262..f9bdecabcc54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -143,6 +143,8 @@ quartodoc = { version = ">=0.6.1,<1", python = ">=3.10,<3.13" } requests = { version = ">=2,<3", python = ">=3.10,<3.13" } scikit-learn = { version = ">=1.3,<2", python = ">=3.10,<3.13" } seaborn = { version = ">=0.12.2,<1", python = ">=3.10,<3.13" } +leafmap = { version = ">=0.29.6,<1", python = ">=3.10,<3.13" } +lonboard = { version = ">=0.5.0,<1", python = ">=3.10,<3.13" } [tool.poetry.extras] # generate the `all` extra using nix run '.#gen-all-extras' diff --git a/requirements-dev.txt b/requirements-dev.txt index eb8fb843e511..d17c0e514b9a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,6 +2,7 @@ aiohttp==3.9.1 ; python_version >= "3.9" and python_version < "4.0" aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "4.0" altair==5.2.0 ; python_version >= "3.10" and python_version < "3.13" annotated-types==0.6.0 ; python_version >= "3.10" and python_version < "3.13" +anywidget==0.7.1 ; python_version >= "3.10" and python_version < "3.13" appdirs==1.4.4 ; python_version >= "3.9" and python_version < "4.0" appnope==0.1.3 ; python_version >= "3.10" and python_version < "3.13" and platform_system == "Darwin" asn1crypto==1.5.1 ; python_version >= "3.9" and python_version < "4.0" @@ -10,10 +11,13 @@ async-timeout==4.0.3 ; python_version >= "3.9" and python_version < "3.11" atpublic==4.0 ; python_version >= "3.9" and python_version < "4.0" attrs==23.1.0 ; python_version >= "3.9" and python_version < "4.0" beartype==0.16.4 ; python_version >= "3.10" and python_version < "3.13" +beautifulsoup4==4.12.2 ; python_version >= "3.10" and python_version < "3.13" bidict==0.22.1 ; python_version >= "3.9" and python_version < "4.0" bitarray==2.8.5 ; python_version >= "3.9" and python_version < "4.0" black==23.11.0 ; python_version >= "3.9" and python_version < "4.0" blackdoc==0.3.9 ; python_version >= "3.9" and python_version < "4.0" +bqplot==0.12.42 ; python_version >= "3.10" and python_version < "3.13" +branca==0.7.0 ; python_version >= "3.10" and python_version < "3.13" build==1.0.3 ; python_version >= "3.9" and python_version < "4.0" cachecontrol[filecache]==0.13.1 ; python_version >= "3.9" and python_version < "4.0" cachetools==5.3.2 ; python_version >= "3.9" and python_version < "4.0" @@ -30,6 +34,7 @@ cligj==0.7.2 ; python_version >= "3.9" and python_version < "4" cloudpickle==3.0.0 ; python_version >= "3.9" and python_version < "4.0" codespell[hard-encoding-detection,toml]==2.2.6 ; python_version >= "3.9" and python_version < "4.0" colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and (sys_platform == "win32" or platform_system == "Windows" or python_version >= "3.10" or os_name == "nt") and (sys_platform == "win32" or platform_system == "Windows" or os_name == "nt" or python_version < "3.13") +colour==0.1.5 ; python_version >= "3.10" and python_version < "3.13" comm==0.2.0 ; python_version >= "3.10" and python_version < "3.13" contourpy==1.2.0 ; python_version >= "3.10" and python_version < "3.13" coverage[toml]==7.3.2 ; python_version >= "3.9" and python_version < "4.0" @@ -55,11 +60,14 @@ executing==2.0.1 ; python_version >= "3.9" and python_version < "4.0" fastjsonschema==2.19.0 ; python_version >= "3.9" and python_version < "4.0" filelock==3.13.1 ; python_version >= "3.9" and python_version < "4.0" fiona==1.9.5 ; python_version >= "3.9" and python_version < "4.0" +folium==0.15.1 ; python_version >= "3.10" and python_version < "3.13" fonttools==4.46.0 ; python_version >= "3.10" and python_version < "3.13" frozenlist==1.4.0 ; python_version >= "3.9" and python_version < "4.0" fsspec==2023.6.0 ; python_version >= "3.9" and python_version < "4.0" gcsfs==2023.6.0 ; python_version >= "3.9" and python_version < "4.0" +gdown==4.7.1 ; python_version >= "3.10" and python_version < "3.13" geoalchemy2==0.14.2 ; python_version >= "3.9" and python_version < "4.0" +geojson==3.1.0 ; python_version >= "3.10" and python_version < "3.13" geopandas==0.14.1 ; python_version >= "3.9" and python_version < "4.0" google-api-core==2.15.0 ; python_version >= "3.9" and python_version < "4.0" google-api-core[grpc]==2.15.0 ; python_version >= "3.9" and python_version < "4.0" @@ -86,8 +94,13 @@ importlib-resources==6.1.1 ; python_version >= "3.9" and python_version < "4.0" impyla==0.19.0 ; python_version >= "3.9" and python_version < "4.0" iniconfig==2.0.0 ; python_version >= "3.9" and python_version < "4.0" installer==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +ipyevents==2.0.2 ; python_version >= "3.10" and python_version < "3.13" +ipyfilechooser==0.6.0 ; python_version >= "3.10" and python_version < "3.13" ipykernel==6.27.1 ; python_version >= "3.10" and python_version < "3.13" +ipyleaflet==0.18.0 ; python_version >= "3.10" and python_version < "3.13" ipython==8.18.1 ; python_version >= "3.9" and python_version < "4.0" +ipytree==0.2.2 ; python_version >= "3.10" and python_version < "3.13" +ipywidgets==8.1.1 ; python_version >= "3.10" and python_version < "3.13" jaraco-classes==3.3.0 ; python_version >= "3.9" and python_version < "4.0" jedi==0.19.1 ; python_version >= "3.9" and python_version < "4.0" jeepney==0.8.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" @@ -97,9 +110,12 @@ jsonschema-specifications==2023.11.2 ; python_version >= "3.10" and python_versi jsonschema==4.20.0 ; python_version >= "3.10" and python_version < "3.13" jupyter-client==8.6.0 ; python_version >= "3.10" and python_version < "3.13" jupyter-core==5.5.0 ; python_version >= "3.10" and python_version < "3.13" +jupyterlab-widgets==3.0.9 ; python_version >= "3.10" and python_version < "3.13" keyring==24.3.0 ; python_version >= "3.9" and python_version < "4.0" kiwisolver==1.4.5 ; python_version >= "3.10" and python_version < "3.13" +leafmap==0.29.6 ; python_version >= "3.10" and python_version < "3.13" locket==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +lonboard==0.5.0 ; python_version >= "3.10" and python_version < "3.13" lz4==4.3.2 ; python_version >= "3.9" and python_version < "4.0" markdown-it-py==3.0.0 ; python_version >= "3.9" and python_version < "4.0" markupsafe==2.1.3 ; python_version >= "3.9" and python_version < "4.0" @@ -120,6 +136,7 @@ numpy==1.26.2 ; python_version >= "3.9" and python_version < "4.0" oauthlib==3.2.2 ; python_version >= "3.9" and python_version < "4.0" oracledb==1.4.2 ; python_version >= "3.9" and python_version < "4.0" packaging==23.2 ; python_version >= "3.9" and python_version < "4.0" +palettable==3.3.3 ; python_version >= "3.10" and python_version < "3.13" pandas==2.1.4 ; python_version >= "3.9" and python_version < "4.0" parso==0.8.3 ; python_version >= "3.9" and python_version < "4.0" parsy==2.1 ; python_version >= "3.9" and python_version < "4.0" @@ -147,6 +164,7 @@ proto-plus==1.23.0 ; python_version >= "3.9" and python_version < "4.0" protobuf==4.25.1 ; python_version >= "3.9" and python_version < "4.0" psutil==5.9.6 ; python_version >= "3.10" and python_version < "3.13" psycopg2==2.9.9 ; python_version >= "3.9" and python_version < "4.0" +psygnal==0.9.5 ; python_version >= "3.10" and python_version < "3.13" ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" pure-eval==0.2.2 ; python_version >= "3.9" and python_version < "4.0" pure-sasl==0.6.2 ; python_version >= "3.9" and python_version < "4.0" @@ -171,7 +189,11 @@ pyopenssl==23.3.0 ; python_version >= "3.9" and python_version < "4.0" pyparsing==3.1.1 ; python_version >= "3.10" and python_version < "3.13" pyproj==3.6.1 ; python_version >= "3.9" and python_version < "4.0" pyproject-hooks==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +pyshp==2.3.1 ; python_version >= "3.10" and python_version < "3.13" +pysocks==1.7.1 ; python_version >= "3.10" and python_version < "3.13" pyspark==3.3.3 ; python_version >= "3.9" and python_version < "4.0" +pystac-client==0.7.5 ; python_version >= "3.10" and python_version < "3.13" +pystac[validation]==1.9.0 ; python_version >= "3.10" and python_version < "3.13" pytest-benchmark==4.0.0 ; python_version >= "3.9" and python_version < "4.0" pytest-clarity==1.0.1 ; python_version >= "3.9" and python_version < "4.0" pytest-cov==4.1.0 ; python_version >= "3.9" and python_version < "4.0" @@ -182,6 +204,7 @@ pytest-repeat==0.9.3 ; python_version >= "3.9" and python_version < "4.0" pytest-snapshot==0.9.0 ; python_version >= "3.9" and python_version < "4.0" pytest-xdist==3.5.0 ; python_version >= "3.9" and python_version < "4.0" pytest==7.4.3 ; python_version >= "3.9" and python_version < "4.0" +python-box==7.1.1 ; python_version >= "3.10" and python_version < "3.13" python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0" pytz==2023.3.post1 ; python_version >= "3.9" and python_version < "4.0" pywin32-ctypes==0.2.2 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "win32" @@ -195,12 +218,14 @@ regex==2023.10.3 ; python_version >= "3.9" and python_version < "4.0" requests-oauthlib==1.3.1 ; python_version >= "3.9" and python_version < "4.0" requests-toolbelt==1.0.0 ; python_version >= "3.9" and python_version < "4.0" requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" +requests[socks]==2.31.0 ; python_version >= "3.10" and python_version < "3.13" rich==13.7.0 ; python_version >= "3.9" and python_version < "4.0" rpds-py==0.13.2 ; python_version >= "3.10" and python_version < "3.13" rsa==4.9 ; python_version >= "3.9" and python_version < "4" ruff==0.1.7 ; python_version >= "3.9" and python_version < "4.0" scikit-learn==1.3.2 ; python_version >= "3.10" and python_version < "3.13" scipy==1.11.4 ; python_version >= "3.10" and python_version < "3.13" +scooby==0.9.2 ; python_version >= "3.10" and python_version < "3.13" seaborn==0.13.0 ; python_version >= "3.10" and python_version < "3.13" secretstorage==3.3.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" setuptools==69.0.2 ; python_version >= "3.9" and python_version < "4.0" @@ -210,6 +235,7 @@ six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" snowflake-connector-python==3.6.0 ; python_version >= "3.9" and python_version < "4.0" snowflake-sqlalchemy==1.5.1 ; python_version >= "3.9" and python_version < "4.0" sortedcontainers==2.4.0 ; python_version >= "3.9" and python_version < "4.0" +soupsieve==2.5 ; python_version >= "3.10" and python_version < "3.13" sphobjinv==2.3.1 ; python_version >= "3.10" and python_version < "3.13" sqlalchemy-views==0.3.2 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy==1.4.50 ; python_version >= "3.9" and python_version < "4.0" @@ -229,6 +255,7 @@ toolz==0.12.0 ; python_version >= "3.9" and python_version < "4.0" tornado==6.4 ; python_version >= "3.10" and python_version < "3.13" tqdm==4.66.1 ; python_version >= "3.9" and python_version < "4.0" traitlets==5.14.0 ; python_version >= "3.9" and python_version < "4.0" +traittypes==0.2.1 ; python_version >= "3.10" and python_version < "3.13" trino[sqlalchemy]==0.327.0 ; python_version >= "3.9" and python_version < "4.0" trove-classifiers==2023.11.29 ; python_version >= "3.9" and python_version < "4.0" typing-extensions==4.9.0 ; python_version >= "3.9" and python_version < "4.0" @@ -239,8 +266,12 @@ virtualenv==20.25.0 ; python_version >= "3.9" and python_version < "4.0" watchdog==3.0.0 ; python_version >= "3.10" and python_version < "3.13" wcwidth==0.2.12 ; python_version >= "3.9" and python_version < "4.0" werkzeug==3.0.1 ; python_version >= "3.9" and python_version < "4.0" +whitebox==2.3.1 ; python_version >= "3.10" and python_version < "3.13" +whiteboxgui==2.3.0 ; python_version >= "3.10" and python_version < "3.13" +widgetsnbextension==4.0.9 ; python_version >= "3.10" and python_version < "3.13" xattr==0.10.1 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "darwin" xxhash==3.4.1 ; python_version >= "3.9" and python_version < "4.0" +xyzservices==2023.10.1 ; python_version >= "3.10" and python_version < "3.13" yarl==1.9.4 ; python_version >= "3.9" and python_version < "4.0" zict==3.0.0 ; python_version >= "3.10" and python_version < "3.13" zipp==3.17.0 ; python_version >= "3.9" and python_version < "4.0"