Getting Started

Easy-EO is a Python package for chainable raster processing, algebra, and visualization. It provides high-level abstractions over Rasterio, NumPy, and Matplotlib, enabling users to perform common earth-observation analysis and visualization tasks efficiently.

This guide shows how to install easy-eo load rasters, perform operations, compute indices, and visualize results.

Installation

Easy-EO requires Python 3.10 or higher and relies on several core geospatial and scientific libraries, including:

  • Rasterio for raster I/O and geospatial transformations.

  • GeoPandas for vector data support.

  • NumPy for numerical and array operations.

  • Matplotlib for visualization of rasters and histograms.

Installing Easy-EO (this current version) automatically installs these dependencies with compatible versions:

  • rasterio>=1.4,<1.5

  • geopandas>=1.1,<1.2

  • numpy>=1.26,<2.2

  • matplotlib>=3.10,<3.11


It is recommended to install easy-eo in a conda environment:

conda create -n env_name python=3.10
conda activate env_name
pip install easy-eo

This will install Easy-EO along with all required dependencies. Make sure your Python environment is version 3.10 or above.


Verify installation by importing the package and checking versions:

import eeo
import rasterio
import geopandas as gpd
import numpy as np
import matplotlib

print("Easy-EO version:", eeo.__version__)
print("Rasterio version:", rasterio.__version__)
print("GeoPandas version:", gpd.__version__)
print("NumPy version:", np.__version__)
print("Matplotlib version:", matplotlib.__version__)
print("Easy-EO installed!")

Core Concepts

Loading a raster

from eeo import load_raster

# Load a raster from disk
ds = load_raster("path/to/image.tif")

This function performs validation and returns an EEORasterDataset. Advanced users may access the underlying rasterio dataset via ds.ds

Properties of the raster can be inspected as:

print(ds.get_crs())       # Coordinate reference system
print(ds.get_shape())     # (height, width)
print(ds.get_transform()) # Affine transform

Accessing bands

# Read a single band
band1 = ds.get_band(1)

# Read multiple bands
bands = [ds.get_band(i) for i in range(1, ds.get_count() + 1)]

Algebra and Arithmetic

Easy-EO supports pixel-wise operations with chainable syntax.

from eeo.ops.algebra import add, subtract, multiply, divide

ds2 = load_raster("path/to/other.tif")

# Add two rasters (auto-aligns if necessary)
result = ds + ds2

# Multiply raster by scalar
result2 = ds * 2

# Chain operations
result3 = (ds - ds2).divide(100)

Note

Supports operator overloading: +, -, *, /, **. auto_align=True ensures datasets with different shapes can be processed safely.

Indices

Easy-EO allows computing normalized or custom indices:

from eeo.analysis import normalized_difference

# NDVI-like computation
ndvi = normalized_difference(ds_nir, ds_red)

# Return as EEORasterDataset
ndvi_ds = ds_nir.normalized_difference(ds_red, return_as_ndarray=False)

Note

Supports chaining with other operations and can return either NumPy arrays or EEORasterDataset.

Clipping, Mosaicking, and Stacking

# Clip raster to bounding box
clipped = ds.clip_raster_with_bbox((0, 0, 1000, 1000))

# Clip using vector (using a geopandas GeodataFrame)
import geopandas as gpd
shapefile = gpd.read_file("vector.shp")
clipped2 = ds.clip_raster_with_vector(shapefile, crop=True)


# Clip using vector (using the path to a geopandas supported vector file)
shapefile_path = r"/path/to/vector_file"
clipped3 = ds.clip_raster_with_vector(shapefile_path, crop=True)

# Mosaic multiple rasters
mosaic_ds = ds.mosaic([ds2, ds3], auto_reproject=True)

# Stack multiple rasters as bands
stacked = ds.stack([ds2, ds3])

Note

  • Auto-reprojects if CRS mismatch

  • Returns a multi-band raster

  • Supports single or multiple rasters as input

Visualization

Visualization functions are terminal operations and should be used last in a chain.

from eeo.viz import (
    plot_raster,
    plot_histogram,
    plot_composite,
    plot_raster_with_histogram
)

# Plot a single band
ds.plot_raster(bands=1, cmap="gray", stretch=True)

# Plot histogram for multiple bands
ds.plot_histogram(bands=[1,2,3], bins=256, sharey=True)

# Plot raster and its histogram
ds.plot_raster_with_histogram(bands=[1,2], stretch=True, sharey=True)

# Plot composite (e.g., RGB)
ds.plot_composite(bands=(4,3,2), stretch=True)

Note

  • Percentile stretching (stretch=True) improves contrast

  • sharey=True aligns histogram axes across multiple bands

  • Multi-band plotting works with single or multiple rasters

  • Composite plotting supports RGB/false-color conventions

Normalization and Standardization

# Z-score standardization
standardized = ds.standardize()

# Min-max normalization
normalized = ds.normalize_min_max(new_min=0, new_max=1)

# Percentile-based normalization
percentile_norm = ds.normalize_percentile(lower_percentile=2, upper_percentile=98)

Note

Useful before visualization or analysis. Can chain with other operations.

Saving and Persistence

To save a dataset to disk, use:

save_raster(path, driver="GTiff")

Example:

ds.normalize_min_max().save_raster("output.tif")

Until this method is called, datasets typically live in memory, allowing fast experimentation without unnecessary disk I/O.


Resource Management

Because EEORasterDataset wraps a Rasterio dataset, it holds file handles and GDAL resources.

To explicitly release resources, call: close()

Example:

ds.close()

Notes:

  • Datasets created from in-memory files (e.g. clipping, mosaicking) become unusable after closing

  • A __del__ method exists as a safety fallback, but explicit close() calls are strongly recommended


Tips

# Use chainable operations for clarity
ds.clip_raster_with_bbox((0,0,1000,1000))
   .normalize_min_max()
   .plot_raster()

Note

  • Terminal operations like plot_raster do not return EEORasterDataset

  • Operator overloading provides concise arithmetic (+, -, *, /)