Skip to main content

A Jupyter widget for CesiumJS 3D globe visualization using anywidget

Project description

CesiumJS Anywidget

A Jupyter widget for interactive 3D globe visualization using CesiumJS and anywidget.

Features

  • 🌍 Interactive 3D Globe: Full CesiumJS viewer integration
  • 🎯 Camera Control: Fly to locations with smooth animations
  • 🔄 Bidirectional Sync: Camera state syncs between Python and JavaScript
  • 🗺️ GeoJSON Support: Load and visualize GeoJSON data
  • 🏔️ Terrain & Imagery: World terrain and satellite imagery
  • 🏙️ Photorealistic 3D Tiles: Google's photorealistic global 3D cities and landscapes
  • 📏 Measurement Tools: Built-in distance, multi-point, and height measurement tools
  • ⚙️ Highly Configurable: Customize viewer options and UI elements

Installation

Using uv (recommended):

uv pip install cesiumjs-anywidget

Or for development:

git clone https://github.com/Alex-PLACET/cesiumjs_anywidget.git
cd cesiumjs_anywidget
uv pip install -e ".[dev]"

Quick Start

from cesiumjs_anywidget import CesiumWidget

# Create and display the widget
widget = CesiumWidget(height="700px")
widget

Usage Examples

Fly to a Location

# Fly to New York City
widget.fly_to(latitude=40.7128, longitude=-74.0060, altitude=50000)

# Fly to Mount Everest
widget.fly_to(latitude=27.9881, longitude=86.9250, altitude=20000)

Advanced Camera Control

# Set camera with custom orientation
widget.set_view(
    latitude=40.7128, 
    longitude=-74.0060, 
    altitude=5000,
    heading=45.0,    # Rotate view 45 degrees
    pitch=-45.0,     # Look at angle instead of straight down
    roll=0.0
)

Read Camera State

# Camera position is synchronized bidirectionally
print(f"Latitude: {widget.latitude:.4f}°")
print(f"Longitude: {widget.longitude:.4f}°")
print(f"Altitude: {widget.altitude:.2f} meters")

Visualize GeoJSON Data

geojson_data = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-74.0060, 40.7128]
            },
            "properties": {
                "name": "New York City"
            }
        }
    ]
}

widget.load_geojson(geojson_data)

Visualize CZML Data

CZML (Cesium Language) is a JSON format for describing time-dynamic graphical scenes. It's particularly useful for animations and complex visualizations.

# Simple CZML example - as Python list
czml_data = [
    {
        "id": "document",
        "name": "Simple CZML",
        "version": "1.0"
    },
    {
        "id": "point",
        "name": "Location",
        "position": {
            "cartographicDegrees": [-74.0060, 40.7128, 0]
        },
        "point": {
            "pixelSize": 10,
            "color": {
                "rgba": [255, 0, 0, 255]
            }
        }
    }
]

widget.load_czml(czml_data)

Or from a JSON string:

import json

# CZML as JSON string
czml_json = json.dumps([
    {"id": "document", "version": "1.0"},
    {
        "id": "satellite",
        "position": {
            "cartographicDegrees": [-75, 40, 500000]
        },
        "point": {"pixelSize": 8, "color": {"rgba": [0, 255, 0, 255]}}
    }
])

widget.load_czml(czml_json)

You can use the czml3 library to generate CZML more easily, then pass the output as a string or list.

Configure Viewer Options

# Create widget with custom configuration
widget = CesiumWidget(
    height="700px",
    enable_terrain=True,
    enable_lighting=True,
    show_timeline=True,
    show_animation=True,
    request_render_mode=True,  # Better idle CPU usage
    maximum_render_time_change=None,  # Uses Infinity (best performance when time-based updates are not needed)
    latitude=27.9881,
    longitude=86.9250,
    altitude=30000
)

With explicit rendering enabled, if you change scene properties through Python and want an immediate frame, call:

widget.request_render()

For time-dynamic scenes (animations/CZML), set a finite value instead of None, for example:

widget.maximum_render_time_change = 0.0
widget.should_animate = True

Google Photorealistic 3D Tiles

Visualize cities and landscapes in stunning photorealistic detail using Google's Photorealistic 3D Tiles:

# Enable photorealistic tiles (recommended method)
widget = CesiumWidget()
widget.enable_photorealistic_3d_tiles(True)

# Fly to a city to see the tiles
widget.fly_to(latitude=40.7128, longitude=-74.0060, altitude=2000, pitch=-45)

# Or configure manually during creation
widget = CesiumWidget(
    enable_photorealistic_tiles=True,
    show_globe=False,  # Disable base globe (recommended)
    enable_terrain=False,  # Disable terrain (tiles include terrain)
    height="700px"
)

Features:

  • Global coverage of major cities and populated areas
  • Photorealistic imagery with 3D buildings and structures
  • Automatic terrain integration
  • Works with all camera controls and measurement tools

See PHOTOREALISTIC_TILES.md for detailed documentation and examples/photorealistic_tiles_demo.ipynb for interactive examples.

Development

Enable hot module replacement for live updates during development:

export ANYWIDGET_HMR=1
jupyter lab

Running Tests

# Install with dev dependencies
uv pip install -e ".[dev]"

# Run all tests
pytest

# Run with coverage
pytest --cov=cesiumjs_anywidget --cov-report=html

# Or use make
make test
make test-cov

See tests/README.md for detailed testing documentation.

Measurement Tools

The widget includes built-in measurement tools for spatial analysis:

Distance Measurement

Measure the distance between two points:

# Enable distance measurement mode
widget.enable_measurement(mode="distance")

# Click two points in the viewer to measure distance
# Results are automatically synced to Python
measurements = widget.get_measurements()
print(f"Distance: {measurements[0]['value']:.2f} meters")

Multi-Point Distance Measurement

Measure distances along a polyline with multiple points:

# Enable multi-point distance measurement
widget.enable_measurement(mode="multi-distance")

# Click multiple points to create a polyline
# Right-click to finish the measurement
# Total distance is calculated automatically

Height Measurement

Measure vertical height from ground to a point (useful for buildings):

# Enable height measurement
widget.enable_measurement(mode="height")

# Click on a point to measure its height above ground
measurements = widget.get_measurements()
print(f"Height: {measurements[0]['value']:.2f} meters")

Managing Measurements

# Get all measurement results
measurements = widget.get_measurements()
for m in measurements:
    print(f"Type: {m['type']}, Value: {m['value']:.2f}m")

# Clear all measurements
widget.clear_measurements()

# Disable measurement mode
widget.disable_measurement()

Loading Measurements from Python

You can programmatically add measurements with specific coordinates:

# Load a distance measurement between two points
measurements_data = [
    {
        "type": "distance",
        "name": "Bridge Length",
        "points": [
            {"coordinates": [-74.0445, 40.6892, 10]},  # [lon, lat, alt]
            {"coordinates": [-73.9626, 40.8075, 10]}
        ]
    }
]
widget.load_measurements(measurements_data)

# Load an area measurement (polygon)
area_data = [
    {
        "type": "area",
        "name": "Central Park",
        "points": [
            {"coordinates": [-73.9812, 40.7681, 0]},
            {"coordinates": [-73.9581, 40.7681, 0]},
            {"coordinates": [-73.9581, 40.8005, 0]},
            {"coordinates": [-73.9812, 40.8005, 0]}
        ]
    }
]
widget.load_measurements(area_data)

# Focus camera on a specific measurement
widget.focus_on_measurement(0)  # Focus on first measurement

Controlling Measurement UI Visibility

You can show/hide the measurement tools and list panel:

# Hide measurement tools (toolbar)
widget.hide_tools()
# Or: widget.show_measurement_tools = False

# Show tools again
widget.show_tools()
# Or: widget.show_measurement_tools = True

# Hide the measurements list panel
widget.hide_list()
# Or: widget.show_measurements_list = False

# Show list again
widget.show_list()
# Or: widget.show_measurements_list = True

# Create a clean viewer without measurement tools
widget = CesiumWidget(
    show_measurement_tools=False,
    show_measurements_list=False
)

Each measurement includes:

  • type: Measurement type ('distance', 'multi-distance', 'height', or 'area')
  • value: Measured value in meters (distance) or square meters (area)
  • points: List of coordinates with lat, lon, alt properties
  • name: Optional name for the measurement (auto-generated if not provided)

API Reference

CesiumWidget

Parameters:

  • latitude (float): Camera latitude in degrees (default: 0.0)
  • longitude (float): Camera longitude in degrees (default: 0.0)
  • altitude (float): Camera altitude in meters (default: 20000000.0)
  • heading (float): Camera heading in degrees (default: 0.0)
  • pitch (float): Camera pitch in degrees (default: -90.0)
  • roll (float): Camera roll in degrees (default: 0.0)
  • height (str): Widget height CSS value (default: "600px")
  • enable_terrain (bool): Enable terrain visualization (default: True)
  • enable_lighting (bool): Enable scene lighting (default: False)
  • show_timeline (bool): Show timeline widget (default: False)
  • show_animation (bool): Show animation widget (default: False)
  • ion_access_token (str): Cesium Ion access token (optional)
  • geojson_data (dict): GeoJSON data to display (optional)
  • czml_data (list): CZML data to display (optional)
  • measurement_mode (str): Active measurement mode (default: "")
  • measurement_results (list): List of measurement results (default: [])
  • show_measurement_tools (bool): Show measurement toolbar (default: True)
  • show_measurements_list (bool): Show measurements list panel (default: True)

Methods:

  • fly_to(latitude, longitude, altitude=10000, duration=3.0): Fly camera to location
  • set_view(latitude, longitude, altitude=10000, heading=0.0, pitch=-90.0, roll=0.0): Set camera view instantly
  • load_geojson(geojson): Load GeoJSON data for visualization
  • load_czml(czml): Load CZML data for time-dynamic visualization
  • enable_measurement(mode="distance"): Enable measurement tool (modes: 'distance', 'multi-distance', 'height', 'area')
  • disable_measurement(): Disable measurement tool
  • get_measurements(): Get all measurement results
  • clear_measurements(): Clear all measurements from viewer
  • load_measurements(measurements): Load measurements from Python data
  • focus_on_measurement(index): Fly camera to specific measurement
  • show_tools(): Show the measurement tools toolbar
  • hide_tools(): Hide the measurement tools toolbar
  • show_list(): Show the measurements list panel
  • hide_list(): Hide the measurements list panel

Examples

See the examples directory for Jupyter notebook demonstrations.

Troubleshooting

If you encounter issues with widget initialization:

from cesiumjs_anywidget import CesiumWidget
widget = CesiumWidget()
widget.debug_info()  # Show debug information

Common fixes:

  • Open browser DevTools (F12) and check the Console tab for errors
  • Try without terrain: widget = CesiumWidget(enable_terrain=False)
  • Ensure you're using JupyterLab 4.0+ or Jupyter Notebook 7.0+
  • Check internet connection (CesiumJS loads from CDN)

See TROUBLESHOOTING.md for detailed debugging guide.

License

Apache License 2.0 - see LICENSE file for details.

Acknowledgments

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

cesiumjs_anywidget-1.0.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cesiumjs_anywidget-1.0.0-py3-none-any.whl (1.4 MB view details)

Uploaded Python 3

File details

Details for the file cesiumjs_anywidget-1.0.0.tar.gz.

File metadata

  • Download URL: cesiumjs_anywidget-1.0.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for cesiumjs_anywidget-1.0.0.tar.gz
Algorithm Hash digest
SHA256 28c14a1b12201cec71fb3e16e8ffad69c965ed30d63fac6d0ace25eee32caa79
MD5 517cbf81301947106e58c0dbd4b24679
BLAKE2b-256 5142453ca18f267f7c91613320f36e4a01f352a86e21d118aadf1017fd7b8790

See more details on using hashes here.

Provenance

The following attestation bundles were made for cesiumjs_anywidget-1.0.0.tar.gz:

Publisher: release_and_publish.yml on Alex-PLACET/cesiumjs_anywidget

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cesiumjs_anywidget-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for cesiumjs_anywidget-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cec6d35195fb74613fdf741415ec91cff60063bd1574886c1d7bbf472db64fe6
MD5 98f49e83abe88c9ce036263471d83b29
BLAKE2b-256 985a64e74fa3d68a531ff46c587c3ab70f81b67ac25db1d3bafcadb6d999eff4

See more details on using hashes here.

Provenance

The following attestation bundles were made for cesiumjs_anywidget-1.0.0-py3-none-any.whl:

Publisher: release_and_publish.yml on Alex-PLACET/cesiumjs_anywidget

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page