Powerful, honest, open-source geospatial visualization with true 3D.
Project description
PyGeoSpace
Powerful, honest, open-source geospatial visualization for Python.
PyGeoSpace is a 2D / true-3D mapping library built on a real geospatial stack (GeoPandas, Shapely, pyproj, deck.gl, PyVista). It reads the common vector and raster formats, renders interactive 2D maps and true 3D terrain, point clouds, and extruded geometry, runs spatial + spectral analytics, and exports interactive HTML, static images, or 3D model files (glTF/STL/PLY/OBJ).
This is the 0.6.0 (Beta) release — "Advanced Visualization & True 3D". It is deliberately honest about its boundaries: every capability under "What works today" is implemented and covered by 81 passing tests. Capabilities under "Roadmap" are not silently stubbed — calling them raises a clear error that names exactly what to install or that the feature is planned.
Install
pip install pygeospace # core: vector IO, analytics, deck.gl, web, CLI
pip install "pygeospace[raster]" # + GeoTIFF/COG/JPEG2000 reading (rasterio)
pip install "pygeospace[3d]" # + true 3D (PyVista, trame, meshio)
pip install "pygeospace[streaming]" # + WebSocket & MQTT clients
pip install "pygeospace[all]" # everything optional
Python 3.10+.
True 3D quickstart (0.6.0)
import pygeospace as pgs
# Terrain straight from an elevation GeoTIFF — interactive in the browser.
m = pgs.Map(mode="3d")
m.add_terrain("srtm_everest.tif", exaggeration=2.0, cmap="gist_earth")
m.export_3d("terrain.html") # interactive vtk.js page
m.render_3d("terrain.png") # static render
m.export_3d("terrain.gltf") # 3D model for Blender/Unity/printing
# Classified LIDAR point cloud in 3D.
pgs.Map(mode="3d").add_pointcloud_3d("forest.las").render_3d("canopy.png")
# Extrude building footprints by a height attribute.
pgs.Map(mode="3d").add_extruded("buildings.shp", "height", factor=1.0).export_3d("city.gltf")
# Scripted camera flythrough.
cam = pgs.Camera3D(position=(0, 0, 5000), focal_point=(0, 0, 0))
cam.fly_to(4000, 4000, 2000, duration=3.0).orbit(45).tilt(20)
m.render_3d("flyover.png", camera=cam)
pygeospace 3d terrain elevation.tif --exaggeration 2.0 -o terrain.html
pygeospace 3d pointcloud data.las --classify -o cloud.html
pygeospace spectral sentinel.tif --indices ndvi,ndwi -o indices/
pygeospace flow od_data.csv -o flow.html
pygeospace export-gltf elevation.tif -o scene.gltf
Quickstart (under 5 minutes)
import pygeospace as pgs
m = pgs.Map()
# Read any vector format; style fluently; results chain.
cities = m.add_layer("cities.geojson")
cities.style(get_fill_color=[255, 90, 0, 200], get_radius=3000)
# Classify an attribute into a choropleth (quantiles / equal_interval / jenks).
from pygeospace.analytics import choropleth
districts = m.add_layer("districts.shp")
choropleth(districts, "population", method="jenks", k=5)
# A geometry pipeline, returning new layers at each step.
buffered = m.add_layer("rivers.gpkg").buffer(250) # 250 m, in true meters
m.fit().save("map.html") # interactive, offline-capable deck.gl page
m.save("map.png", dpi=300) # static export
Command line:
pygeospace visualize cities.geojson -o map.html --style choropleth --attribute pop --method jenks
pygeospace export cities.geojson -o map.png --dpi 300
pygeospace serve cities.geojson --port 8000 # live preview in the browser
pygeospace serve --api --port 8000 # REST CRUD API
pygeospace info data.gpkg
What works today (0.5.0)
| Area | Capability | Status |
|---|---|---|
| IO | Shapefile, GeoJSON, GeoPackage, KML, GPX, GML (via GeoPandas/OGR) | ✅ |
| CSV with coordinate columns | ✅ | |
| PostGIS query → layer | ✅ | |
| Format autodetect (extension + magic bytes) | ✅ | |
| GeoTIFF / COG / JPEG2000 read | ✅ with [raster] |
|
| LAS/LAZ point cloud read | ✅ with [pointcloud] |
|
| Vector viz | deck.gl scatter / GeoJSON / heatmap / hexagon-bin | ✅ |
| Choropleth: quantiles, equal-interval, Jenks natural breaks | ✅ | |
| pandas-query attribute filtering (instant, no reload) | ✅ | |
| CRS auto-reprojection to EPSG:4326 | ✅ | |
| Raster | Multi-band arrays, on-the-fly NDVI, hillshade | ✅ |
| Analytics | Buffer (true meters via UTM), intersection, difference, dissolve | ✅ |
| KMeans / DBSCAN clustering, hex/grid binning (H3 if installed) | ✅ | |
| 3D (0.6.0) | True 3D terrain from rasters (exaggeration, elevation colormap) | ✅ [3d] |
| 3D point clouds with LAS-classification coloring; polygon extrusion; cut planes | ✅ [3d] |
|
| Render to PNG + interactive HTML; export glTF/GLB/STL/PLY/OBJ/VTK | ✅ [3d] |
|
Camera3D: fly_to / orbit / tilt / path recording |
✅ [3d] |
|
| Tilted (pitch/bearing) pseudo-3D deck.gl view | ✅ | |
| Raster (0.6.0) | Spectral indices NDVI/NDWI/NDBI/SAVI/EVI; band compositing; slope | ✅ |
| On-the-fly reprojection + multi-raster mosaicing | ✅ [raster] |
|
| Vector (0.6.0) | Contour lines from scattered points; O-D flow maps (arcs); H3 hexbins | ✅ |
| Streaming | WebSocket & MQTT clients; trail buffer; threshold alerts | ✅ with [streaming]¹ |
| Publishing | Interactive HTML, static PNG/PDF, Jupyter inline (_repr_html_) |
✅ |
| FastAPI dev server + REST CRUD API | ✅ | |
| Extensibility | Decorator plugin system (data sources, renderers, tools) | ✅ |
¹ The clients are real and connect to any reachable endpoint. Connecting to a specific public broker requires network access to that host.
Roadmap — what is not in 0.5.0
These are tracked in ROADMAP.md. Where the public API touches
them, it raises a clear, actionable error rather than pretending.
| Planned for | Feature |
|---|---|
| 0.6.0 | True PyVista 3D globe + terrain extrusion; raster↔vector opacity blending in the static renderer; vector-tile generation |
| 0.7.0 | Getis-Ord Gi* hotspot maps with significance shading; zonal statistics charts; OSMnx shortest-path routing |
| 1.0.0 | WebGPU renderer for multi-million-point scenes; COG tile server with LRU disk cache; Dask-parallel distributed loading; flow-map & time-slider widgets as first-class UI |
Design notes
- Honesty over surface area. A smaller set of things that genuinely work beats a large set that breaks on first use.
- Real units. Buffers reproject to the local UTM zone so "250 m" means 250 meters, not 250 degrees.
- Lazy optional deps. Heavy/optional libraries (rasterio, laspy, paho-mqtt, h3, pyvista) are imported only when used, with install hints on failure.
Development
pip install -e ".[dev]"
pytest # 43 tests
ruff check .
License
MIT.
3D & 2D Gallery
Rendered headlessly by the test/example suite (see examples/):
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pygeospace-0.6.3.tar.gz.
File metadata
- Download URL: pygeospace-0.6.3.tar.gz
- Upload date:
- Size: 77.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06297eb652bcb1aef255d4b218cb0eca60f987134eb8ddc303ad26b514a4e62b
|
|
| MD5 |
59900f5ffe22908030520f49d148d457
|
|
| BLAKE2b-256 |
9e61d1a5e35b211697097c3ac352e5ef529304d81040f99d54712fcbd7c28d20
|
File details
Details for the file pygeospace-0.6.3-py3-none-any.whl.
File metadata
- Download URL: pygeospace-0.6.3-py3-none-any.whl
- Upload date:
- Size: 71.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5e28e814e34a00476d7ff0611ca2282b088735254b022bfd9402baa7ec8e491
|
|
| MD5 |
970a3ac0098c29e25a6b5e14c175b576
|
|
| BLAKE2b-256 |
01d0ac4ba9bb8a8936096d609a93b73ed1c32006a57e7078785b6fc63ece1c60
|