Skip to content
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
96628ab
Create GISDocuments as untitled when no path provided
mfisher87 Apr 14, 2025
b1ee829
Remove `save_as()` method from GISDocument API, re-add `export_to_qgi…
mfisher87 Apr 14, 2025
c275e6e
Prefer `const`
mfisher87 Apr 14, 2025
691a60b
Fix unit test
mfisher87 Apr 14, 2025
287c742
Test untitled document numbering
mfisher87 Apr 14, 2025
6c400a5
Update docstring
mfisher87 Apr 14, 2025
31cd634
Stub out geo_debug function with jupyterlab-sidecar
mfisher87 Jan 16, 2025
d392901
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 16, 2025
8c6b937
WIP
mfisher87 Jan 23, 2025
dec08a6
Add ESPM-157 notebook as example user of geo-debug workflow WIP
mfisher87 Jan 27, 2025
e6a0570
Use correct .jGIS extension
mfisher87 Jan 28, 2025
2e56f0c
Dunno, rebase me later
mfisher87 Jan 28, 2025
9f3b6b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 28, 2025
ea3f08e
Open JGIS in sidecar
mfisher87 Mar 25, 2025
71b5540
Create an anonymous project
mfisher87 Mar 27, 2025
6faedf4
Open in a new JupyterLab window/tab!
mfisher87 Mar 27, 2025
d26280a
Update TODO comments
mfisher87 Mar 27, 2025
27285fd
Rename geo_debug -> explore
mfisher87 Apr 15, 2025
3816508
Explore explore function at jupytergis package
mfisher87 Apr 15, 2025
cb82c6f
Update docstring and parameter type
mfisher87 Apr 16, 2025
41662ae
Open JGIS Document as a full window, not widget
mfisher87 Apr 16, 2025
3fdee4f
Hack around document opening but not displaying layers as expected
mfisher87 Apr 16, 2025
c00844e
Switch back to sidecar approach, use CSS to handle filling space
mfisher87 Apr 17, 2025
eba50f1
Add dedicated explore example
mfisher87 Apr 17, 2025
a565ff4
Cleanup OBE comment
mfisher87 Apr 17, 2025
41f0a5e
Remove OBE test
mfisher87 Apr 17, 2025
d531178
Extract sidecar-opening to GISDocument API
mfisher87 Apr 19, 2025
b649e44
Dynamically determine type of object passed to explore()
mfisher87 Apr 19, 2025
e8d054f
Update example notebook to explore a geodataframe
mfisher87 Apr 19, 2025
d4d0de0
Remove debugging print statement
mfisher87 Apr 19, 2025
e621cd8
Move "smart" layer add into GISDocument method
mfisher87 Apr 19, 2025
a29b0c2
Add basemap parameter to `explore()`
mfisher87 Apr 19, 2025
a083bdf
Autodoc `explore()`
mfisher87 Apr 19, 2025
a17339f
Bugfix: don't pass name=None to methods that don't support it
mfisher87 Apr 19, 2025
d8a2355
Fix incorrect docstring raises directive
mfisher87 Apr 19, 2025
c32623a
Install jupytergis metapackage in docs environment
mfisher87 Apr 20, 2025
761e94a
Fix CSS to properly use vertical space in linked output & sidecar views
mfisher87 Apr 20, 2025
baba817
Fix autodoc typo
mfisher87 Apr 22, 2025
b47a01e
Fix layer panel not updating in sidecar view
mfisher87 Apr 23, 2025
ddf3d48
Copy docstring raises entries from underlying method docstring
mfisher87 Apr 23, 2025
0b2eab4
Attempt to fix lite integration tests
mfisher87 Apr 24, 2025
1503af3
Add note about CSS eventually added in JupyterLab
mfisher87 Apr 24, 2025
595dfa3
Move explore module into notebook subpackage
mfisher87 Apr 24, 2025
119c281
Make generic add_layer method a private internal function
mfisher87 Apr 24, 2025
9994796
Merge branch 'main' into sidecar-experiment
mfisher87 Apr 24, 2025
56bc8bd
Missing sidecar and export
martinRenou Apr 25, 2025
dff4346
Merge branch 'main' into sidecar-experiment
martinRenou Apr 25, 2025
9a909e4
Missing sidecar in docs
martinRenou Apr 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/environment-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ dependencies:
# See: https://github.com/geojupyter/jupytergis/issues/585
- ../python/jupytergis_core
- ../python/jupytergis_lab
- ../python/jupytergis
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is the culprit for the failure in the docs. We can't have jupytergis installed in the lite deployment of the docs.

It needs to be jupytergis_lite or nothing.

10 changes: 8 additions & 2 deletions docs/user_guide/python_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ doc

Once the document is opened/created, you can start creating GIS layers.

## `GISDocument` API Reference
## `explore`

```{eval-rst}
.. autoclass:: jupytergis_lab.GISDocument
.. autofunction:: jupytergis.explore
```

## `GISDocument`

```{eval-rst}
.. autoclass:: jupytergis.GISDocument
:members:
```
111 changes: 111 additions & 0 deletions examples/explore.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c3f4096f-cbd3-43e8-a986-520681f03581",
"metadata": {},
"source": [
"# ESPM 157 - Intro to Spatial Data\n",
"\n",
"<https://espm-157.carlboettiger.info/spatial-1>\n",
"\n",
"Install dependencies:\n",
"\n",
"```bash\n",
"micromamba install geopandas ibis-duckdb\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b76ae1f0-334e-41c0-9533-407c879b4ad6",
"metadata": {},
"outputs": [],
"source": [
"import ibis\n",
"\n",
"con = ibis.duckdb.connect()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "837aa4e0-5eeb-48c1-97ce-3f8706503911",
"metadata": {},
"outputs": [],
"source": [
"redlines = con.read_geo(\n",
" \"/vsicurl/https://dsl.richmond.edu/panorama/redlining/static/mappinginequality.gpkg\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4d3319fa-b3b4-4931-b073-98b649e41b65",
"metadata": {},
"outputs": [],
"source": [
"city = redlines.filter(redlines.city == \"New Haven\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34f7f4d6-28d6-4716-8e03-ac32c6ae3bb7",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"city_gdf = city.head().execute()\n",
"city_gdf.plot()"
]
},
{
"cell_type": "markdown",
"id": "d37a610a-1444-43a3-900f-dfe16a890ab9",
"metadata": {},
"source": [
"## OK, but what about spatial context?\n",
"\n",
"I want to explore this data more interactively."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e68aaac-dfc0-42d8-a3b9-05fce59524b2",
"metadata": {},
"outputs": [],
"source": [
"from jupytergis import explore\n",
"\n",
"# Open a new exploration window\n",
"explore(city_gdf, layer_name=\"New Haven\", basemap=\"dark\")"
]
}
],
"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.12.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions packages/base/src/panelview/components/layers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ function LayersBodyComponent(props: IBodyProps): JSX.Element {
model?.sharedModel.layersChanged.connect(updateLayers);
model?.sharedModel.layerTreeChanged.connect(updateLayers);

updateLayers();
return () => {
model?.sharedModel.layersChanged.disconnect(updateLayers);
model?.sharedModel.layerTreeChanged.disconnect(updateLayers);
Expand Down
2 changes: 1 addition & 1 deletion python/jupytergis/jupytergis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = "0.4.4"

from jupytergis_lab import GISDocument # noqa
from jupytergis_lab import GISDocument, explore # noqa
1 change: 1 addition & 0 deletions python/jupytergis_lab/jupytergis_lab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
__version__ = "dev"

from .notebook import GISDocument # noqa
from .explore import explore


def _jupyter_labextension_paths():
Expand Down
75 changes: 75 additions & 0 deletions python/jupytergis_lab/jupytergis_lab/explore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Literal, Optional

from jupytergis_lab import GISDocument


@dataclass
class Basemap:
name: str
url: str


BasemapChoice = Literal["light", "dark", "topo"]
_basemaps: dict[BasemapChoice, list[Basemap]] = {
"light": [
Basemap(
name="ArcGIS dark basemap",
url="https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}.pbf",
),
Basemap(
name="ArcGIS dark basemap reference",
url="https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer/tile/{z}/{y}/{x}.pbf",
),
],
"dark": [
Basemap(
name="ArcGIS light basemap",
url="https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}.pbf",
),
Basemap(
name="ArcGIS light basemap reference",
url="https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Reference/MapServer/tile/{z}/{y}/{x}.pbf",
),
],
"topo": [
Basemap(
name="USGS topographic basemap",
url="https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}",
),
],
}


def explore(
data: str | Path | Any,
*,
layer_name: Optional[str] = "Exploration layer",
basemap: BasemapChoice = "topo",
) -> GISDocument:
"""Run a JupyterGIS data interaction interface alongside a Notebook.

:param data: A GeoDataFrame or path to a GeoJSON file.

:raises FileNotFoundError: Received a file path that doesn't exist.
:raises NotImplementedError: Received an input value that isn't supported yet.
:raises TypeError: Received an object type that isn't supported.
:raises ValueError: Received an input value that isn't supported.
"""
doc = GISDocument()

for basemap_obj in _basemaps[basemap]:
doc.add_raster_layer(basemap_obj.url, name=basemap_obj.name)

doc.add_layer(data, name=layer_name)

# TODO: Zoom to layer. Currently not exposed in Python API.

doc.sidecar(title="JupyterGIS explorer")

# TODO: should we return `doc`? It enables the exploration environment more usable,
# but by default, `explore(...)` would display a widget in the notebook _and_ open a
# sidecar for the same widget. The user would need to append a semicolon to disable
# that behavior. We can't disable that behavior from within this function to the
# best of my knowlwedge.
Loading
Loading