Saterys โ Scalable Analysis Toolkit for Earth Remote sYStemS
Project description
SATERYS
Scalable Analysis Toolkit for Earth Remote sYStemS
A modern geospatial pipeline builder with interactive node-based workflows
๐ Documentation โข ๐ Quick Start โข ๐ฏ Examples โข ๐ Plugins
๐ Overview
SATERYS is a powerful geospatial analysis platform that combines the best of modern web technologies with robust geospatial processing capabilities. Build complex Earth observation workflows using an intuitive drag-and-drop interface, execute Python-based analysis nodes, and visualize results on interactive maps.
โจ Key Features
๐จ Visual Pipeline Builder
|
โก High-Performance Backend
|
๐ฐ๏ธ Geospatial Native
|
๐ Extensible & Modular Architecture
|
๐งฉ Plugin Ecosystem
|
๐ฅ๏ธ Modern Web UI
|
๐ Quick Start
Installation
# Install SATERYS
pip install saterys
# Verify installation
saterys --help
Launch the Application
# Start SATERYS server
saterys
# Access the web interface at http://localhost:8000
The application will automatically:
- ๐ Discover all available plugins
- ๐ Start the FastAPI backend
- ๐จ Serve the Svelte frontend
- ๐ Open your default browser
Development Mode
For development with hot-reload:
# Start with auto-reload
saterys --dev
๐ฏ Examples
Basic Workflow: Hello World
- Add a Node: Click "Add Node" and select "hello"
- Configure: Set the name parameter to "SATERYS"
- Execute: Click the "Run" button
- View Results: Check the output in the logs panel
# This runs automatically when you execute the hello node
def run(args, inputs, context):
name = args.get("name", "world")
return {"text": f"hello {name}"}
Geospatial Workflow: NDVI Calculation
Create a vegetation index from satellite imagery:
# 1. Add a raster input node
# 2. Set path to your multispectral image (e.g., Landsat, Sentinel)
# 3. Add NDVI calculation node
# 4. Configure band indices (e.g., red=4, nir=5 for Landsat 8)
# 5. Connect nodes and execute
Example NDVI Node Configuration:
{
"red_band": 4,
"nir_band": 5,
"output_path": "./results/ndvi_output.tif",
"dtype": "float32"
}
Custom Processing with Script Node
Write inline Python for custom analysis:
# Script node example - band math
import numpy as np
import rasterio
def process_raster(input_raster):
with rasterio.open(input_raster["path"]) as src:
# Read bands
red = src.read(4).astype(float)
nir = src.read(5).astype(float)
# Custom vegetation index
evi = 2.5 * ((nir - red) / (nir + 6 * red - 7.5 * blue + 1))
return {"custom_index": evi}
๐ Documentation
Built-in Nodes
| Node Type | Description | Use Case |
|---|---|---|
| ๐ข raster.input | Load GeoTIFF/COG files | Data ingestion |
| ๐ฟ raster.ndvi | Calculate NDVI | Vegetation analysis |
| ๐ raster.ndwi | Calculate NDWI | Water body detection |
| ๐ raster.pca | Principal Component Analysis | Dimensionality reduction |
| โ sum | Sum numeric values | Basic arithmetic |
| ๐ hello | Hello world example | Testing/demos |
| ๐ script | Custom Python code | Flexible processing |
API Endpoints
The FastAPI backend provides REST endpoints for integration:
# Get available node types
GET /node_types
# Execute a node
POST /run_node
{
"nodeId": "unique-id",
"type": "raster.ndvi",
"args": {"red_band": 4, "nir_band": 5},
"inputs": {...}
}
# Register raster for preview
POST /preview/register
{
"id": "my-raster",
"path": "/path/to/file.tif"
}
# Get map tiles
GET /preview/tile/{id}/{z}/{x}/{y}.png
๐ Plugins
SATERYS features a powerful plugin-first architecture that allows you to extend functionality without modifying the core.
Plugin System
The plugin system provides two extension points:
- Backend Plugins (Python): Add new REST API endpoints using FastAPI
- Frontend Plugins (TypeScript): Add toolbar buttons, menus, canvas overlays, and custom nodes
Quick Start: Running the Demo
-
Build the frontend (includes plugin build):
cd saterys/web npm install npm run build
-
Run the server:
cd ../.. saterys
-
Access the UI at
http://localhost:8000 -
Click "Hello Plugin" button in the toolbar
- Shows toast notification
- Calls
/plugins/starter/echobackend endpoint - Displays "Echo OK" on success
Creating Your Own Plugins
Backend Plugin Structure:
plugins/
my_plugin/
__init__.py # Plugin code
pyproject.toml # Entry point registration
Frontend Plugin Structure:
saterys/web/plugins/
@saterys/my-plugin/
src/index.ts # Plugin code
tsconfig.json # TypeScript config
package.json # Build scripts
See docs/plugin-api.md for complete documentation including:
- Backend plugin API with FastAPI router integration
- Frontend registry functions (toolbar, menus, overlays, nodes)
- AppContext API for accessing core services
- Authentication integration
- Best practices and examples
Starter Plugins
The repository includes fully-functional starter plugins:
- Python:
plugins/saterys_plugin_starter/- Echo endpoint example - UI:
saterys/web/plugins/@saterys/plugin-starter/- Toolbar button + API call
Use these as templates for creating your own plugins!
๐งฉ Creating Plugins
SATERYS uses a simple plugin architecture. Create custom nodes by adding Python files to a nodes/ directory:
Basic Plugin Structure
# nodes/my_custom_node.py
NAME = "my.custom.node" # Unique identifier
DEFAULT_ARGS = { # Default configuration
"param1": "default_value",
"param2": 42
}
def run(args, inputs, context):
"""
Execute the node logic
Args:
args: Node configuration parameters
inputs: Data from connected upstream nodes
context: Runtime context (nodeId, etc.)
Returns:
Dictionary with output data
"""
# Your processing logic here
result = process_data(args, inputs)
return {
"type": "custom",
"data": result,
"metadata": {...}
}
Raster Processing Plugin Example
# nodes/custom_filter.py
NAME = "raster.custom_filter"
DEFAULT_ARGS = {
"filter_size": 3,
"operation": "gaussian"
}
def run(args, inputs, context):
import rasterio
import numpy as np
from scipy import ndimage
# Get input raster
raster_input = next(
(inp for inp in inputs.values()
if inp.get("type") == "raster"),
None
)
if not raster_input:
raise ValueError("No raster input found")
# Process the raster
with rasterio.open(raster_input["path"]) as src:
data = src.read(1)
# Apply filter
if args["operation"] == "gaussian":
filtered = ndimage.gaussian_filter(
data,
sigma=args["filter_size"]
)
# Save result...
output_path = "/tmp/filtered_result.tif"
# ... saving logic here ...
return {
"type": "raster",
"path": output_path,
"operation": "custom_filter"
}
Plugin Discovery
SATERYS automatically discovers plugins from:
- Built-in nodes:
saterys/nodes/(package installation) - User nodes:
./nodes/(current working directory)
Simply restart the application after adding new plugins!
๐ ๏ธ Advanced Usage
Environment Configuration
# Custom host and port
export SATERYS_HOST=0.0.0.0
export SATERYS_PORT=8080
# Raster cache directory
export RASTER_CACHE=./my_cache
# Development frontend origin (for CORS)
export SATERYS_DEV_ORIGIN=http://localhost:5173
Docker Usage
FROM python:3.10-slim
RUN pip install saterys
# Add your custom nodes
COPY nodes/ /app/nodes/
WORKDIR /app
EXPOSE 8000
CMD ["saterys", "--host", "0.0.0.0"]
Programmatic Usage
import uvicorn
from saterys.app import app
# Customize the FastAPI app
@app.get("/custom")
def custom_endpoint():
return {"message": "Custom endpoint"}
# Run programmatically
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
๐ค Contributing
We welcome contributions! Here's how to get started:
Development Setup
# Clone the repository
git clone https://github.com/bastian6666/SATERYS.git
cd SATERYS
# Install in development mode
pip install -e .
# Install frontend dependencies (if modifying UI)
cd saterys/web
npm install
# Start development server
npm run dev
Code Style
- Follow PEP 8 for Python code
- Use type hints where possible
- Add docstrings for public functions
- Test your changes before submitting
Submitting Changes
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- FastAPI: For building modern, high-performance APIs with ease.
- Uvicorn: An ASGI server for lightning-fast application deployment.
- Pydantic: Ensuring data validation and management is smooth and reliable.
- NumPy: The foundation for numerical computing in Python.
- rio-tiler: Efficient raster tiling and preview generation.
- Rasterio: Simplifying geospatial raster data I/O.
- Fiona: A powerful library for vector data handling (GPKG/SHP).
- PyProj: For seamless coordinate reference system transformations.
- Shapely: Geometry manipulation made easy.
- APScheduler: A flexible scheduling library for background jobs.
- SQLAlchemy: The go-to library for database interaction and ORM functionality.
- pytz: Comprehensive timezone support.
- tzlocal: Simplifies local timezone detection.
๐ Support
- ๐ Documentation
- ๐ Issue Tracker
- ๐ฌ Discussions
- ๐ง Email
Project details
Release history Release notifications | RSS feed
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 saterys-0.4.2.tar.gz.
File metadata
- Download URL: saterys-0.4.2.tar.gz
- Upload date:
- Size: 208.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b6649eb2b8643aa175a9fdda88d72a72020a0314b75bed43f604c3d719d84cd
|
|
| MD5 |
11c1cd6a9b397772988a8b5839ad2011
|
|
| BLAKE2b-256 |
60314ef6d64e77439b19449209b616897ec6252c880ab1204c17592b2d73ff95
|
File details
Details for the file saterys-0.4.2-py3-none-any.whl.
File metadata
- Download URL: saterys-0.4.2-py3-none-any.whl
- Upload date:
- Size: 210.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2270c1b1a92dffeba773e34068ef6be856c9dde8b94888cec6ea5b9962744a95
|
|
| MD5 |
ff41a4a633ba436d81ab13c7b119d4af
|
|
| BLAKE2b-256 |
54983b37735c429b52996785288985991aee413826498a0505eb67f1c6283911
|