Skip to main content

Build Status

ipygis

A bridge to GIS libraries running in the browser.

Development installation

micromamba create -n ipygis
micromamba activate ipygis
micromamba install xeus-python pip nodejs
pip install jupyterlab -e .
jupyter labextension develop --overwrite .

When making changes to the JavaScript code, you can just recompile that part:

jlpm run build

Install the Python test and lint tools with pip install -e '.[test]', then run:

python -m ruff check ipygis tests
python -m ruff format --check ipygis tests
python -m pytest tests

Ruff checks basic Python errors and import ordering. To apply its automatic fixes, use python -m ruff check ipygis tests --fix. Format the Python code with python -m ruff format ipygis tests; the formatter is configured to use single quotes.

Running the example notebooks

Run examples/build_time.ipynb first to create the Icechunk repository. This notebook cannot run in JupyterLite because of incompatible libraries, but the created repository is the only thing that will be needed by examples/run_time.ipynb.

That notebook uses a read-only API modeled on Zarr-Python’s asynchronous interface. Zarrita reads, decodes, and slices arrays in the browser, returning NumPy arrays to Python without Zarr-Python’s synchronous bridge. The browser uses icechunk-js by default. This backend requires no COOP/COEP headers or shared memory. You can change the backend to "@earthmover/icechunk" but this is a WASM library that needs SharedArrayBuffer and so the server must send COOP/COEP headers. In this case JupyterLab must use a special configuration:

jupyter lab --config=./jupyter_server_config.json

Both readers are installed from npm. No local Icechunk checkout or WASM preparation step is required. The published @earthmover/icechunk 2.0.3 package does not include the browser HTTP virtual-chunk callback; use backend="icechunk-js" for the HydroSHEDS runtime notebook.

Asynchronous array reads

from ipygis.zarr import asynchronous as zarr

group = await zarr.open_group(session.store, mode="r")
array = await group.getitem("0")
print(array.shape, array.dtype, array.chunks)
region = await array.getitem((10, slice(100, 200), slice(200, 300)))
point = await array.getitem((10, 100, 200))

You can also use await zarr.open_array(session.store, path="0", mode="r"). Reads support integers (including negative indices), ellipses, and positive-step slices. Integer and floating-point dtypes from 8-bit integers through 64-bit integers/floats are supported; 64-bit integers are transferred as binary data. Zarr v3 variable-length strings are returned as NumPy object arrays (or Python strings for point selections). Numeric point selections return NumPy scalars; other numeric selections return NumPy arrays. Metadata attributes are local snapshots, not a write API. Writing, fancy/boolean indexing, new axes, negative slice steps, and other nonnumeric dtypes are unsupported. TIFF LZW decoding is registered in JavaScript automatically. Other codecs must be supported by Zarrita; this API does not apply xarray's CF decoding or geospatial coordinate selection. Close the session after finishing all reads.

The existing session.store remains usable with Zarr-Python. The new array API uses its browser backend directly; Python does not fetch or decode the chunks.

Asynchronous xarray reads

Use ipygis's async opener to construct an xarray dataset from the same store:

from ipygis.xarray import open_zarr_async

ds = await open_zarr_async(session.store)
region = await ds.isel(y=slice(100, 200), x=slice(200, 300)).load_async()
# If the dataset contains x and y coordinate arrays:
point = await ds.sel(x=10.5, y=48.5, method="nearest").load_async()

Use your dataset's dimension names in place of x and y. Dimensions must be stored in Zarr v3 dimension_names or Zarr v2 _ARRAY_DIMENSIONS attributes. Coordinate arrays must already exist; the opener does not derive them from TIFF georeferencing.

This uses Zarrita for array reads, without calling xarray.open_zarr() or Zarr-Python's synchronous API. Raster data stays lazy until load_async(); synchronous operations such as accessing unloaded .values raise an error. Coordinate arrays for dimension indexes are read asynchronously while opening so that .sel() can work. Pass create_default_indexes=False to skip those reads and use .isel() instead.

CF masks and scale factors are decoded lazily. CF datetime arrays are currently loaded asynchronously before decoding because xarray's datetime decoder probes values synchronously; use decode_times=False to leave those arrays lazy. The browser API supports numeric arrays and Zarr v3 strings. Advanced indexing may read a larger bounding region before selecting the requested values in Python. Keep the session open until all reads finish; closing the dataset does not close it.

Geographic mosaics

mosaic_async combines georeferenced xarray DataArrays into one lazy array:

from ipygis.xarray import mosaic_async

mosaic = await mosaic_async(
    sources, x="longitude", y="latitude", crs="EPSG:4326",
)
region = await mosaic.sel(
    longitude=slice(-110, -109), latitude=slice(50, 49),
).load_async()

Each source must be a numeric 2-D array with one-dimensional pixel-center coordinates, ascending in x and descending in y. Coordinates must have at least two values per axis, the same regular spacing, and aligned centers. Sources must share their dtype and CRS, and must not overlap. The crs argument declares their common CRS; source crs attributes, when present, must match it exactly. There is no reprojection or resampling. Chunk boundaries can differ between sources.

Opening loads only coordinates. Reads fetch intersecting source slices and assemble the requested output in Python. Missing areas are filled with NaN; integer arrays require an explicit integer fill_value to preserve precision. The result supports xarray selection and load_async(); synchronous reads of unloaded values raise an error. Advanced indexing may fetch a larger bounding region. Keep all source stores open until reads finish.

The HydroSHEDS notebooks retain the virtual tile collection in Icechunk and construct this mosaic at runtime from the tile origins and pixel spacing. A single stored virtual grid cannot join these TIFFs because their edges fall inside the mosaic's chunks. The mosaic reader handles those boundaries after Zarrita decodes the selected source chunks.

Asynchronous Zarr exports

Write an xarray Dataset to a new directory through Jupyter Contents:

from ipygis.xarray import to_zarr_async

await to_zarr_async(
    region.to_dataset(name="elevation"),
    "exports/region.zarr",
    encoding={"elevation": {"chunks": (256, 256)}},
)

The path is relative to the Jupyter contents root. JupyterLab saves the files on its server; JupyterLite uses its configured browser storage. The writer uses app.serviceManager.contents and base64 file writes. Zarrita encodes the chunks in the browser, while Python loads and transfers one output chunk at a time. Default numeric chunks are approximately 1 MiB or smaller. No Python filesystem access or synchronous Zarr API is used.

The output is a regular, uncompressed Zarr v3 group with dimensions, coordinates, and JSON attributes. Numeric and string arrays are supported; object arrays must contain only strings. Source storage encodings are not copied: decoded values are exported. Only the chunks output encoding option is currently supported. Datetimes, booleans, complex arrays, appending, region writes, and consolidated metadata are not yet supported.

Existing destinations are rejected (mode="w-"). Do not export concurrently to the same path: Jupyter Contents does not offer atomic exclusive creation. An interrupted or failed export may leave a partial directory; inspect or remove it before retrying. Source sessions must remain open until the export completes.

Reopen an exported store through the same Jupyter Contents service:

from ipygis.xarray import open_zarr_async

with await open_zarr_async("exports/region.zarr") as ds:
    region = await ds.isel(latitude=slice(0, 100)).load_async()

Use the dimension names present in your dataset. A path-based dataset owns its browser connection; close it after the required async reads, using with as above or ds.close(). Already loaded results remain usable after closing.

Release files for ipygis 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ipygis 0.1.4
File Size Uploaded
ipygis-0.1.4.tar.gz 8.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for ipygis 0.1.4
File Interpreter ABI Platform
ipygis-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 21.5 MB

Release files / ipygis-0.1.4.tar.gz

Download URL ipygis-0.1.4.tar.gz
Size 8.6 MB
Tags Source
SHA-256 checksum
How to use checksums
f3e3d028d559814c7debd67de326575868a3bc710a8cc74830029b6ea68e04bf
BLAKE2b-256 checksum
How to use checksums
8bbb626b5d0b50f03af9d2db161e8c9836291722092451e6eff76c0e91811d37
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / ipygis-0.1.4-py3-none-any.whl

Download URL ipygis-0.1.4-py3-none-any.whl
Size 12.8 MB
Tags Python 3
SHA-256 checksum
How to use checksums
0e69cf21b8ece0f86fd94678447704d7554e45e631b968d201d285a6adf05ff5
BLAKE2b-256 checksum
How to use checksums
7d02f8f18156a1cdb596dbc61ef5a22b60907f12ddb238234487d1974c30513c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page