Skip to content

Repository files navigation

xeo

Awesome Earth Observation Instruments in Python

Awesome PyPI conda-forge arXiv Awesome Earth Observation Instruments tests GitHub Sponsors Buy me a coffee Ko-fi Twitter


Awesome Earth Observation Instruments Catalogue: https://github.com/awesome-spectral-indices/awesome-earth-observation-instruments

GitHub: https://github.com/awesome-spectral-indices/xeo


About xeo

xeo is the Python interface to the Awesome Earth Observation Instruments catalogue. It turns the catalogue into a small, exploratory API for discovering instruments, inspecting their metadata, searching across the collection, and loading spectral bands and spectral response functions as pandas DataFrames when they are available.

A snapshot of the catalogue is bundled with each xeo release. This keeps catalogue exploration local and makes it straightforward to use instrument metadata in Python workflows.

What is the Awesome Earth Observation Instruments catalogue?

Awesome Earth Observation Instruments is a community-driven, machine-readable catalogue of instruments used to observe Earth. It organizes spectral, spatial, temporal, operational, platform, and data-access metadata under a consistent schema so that instruments from different missions and operators can be discovered and compared.

The catalogue is the source of the instrument records; xeo is the Python interface to those records. Contributions to instrument metadata, bands, SRFs, or catalogue schemas belong in the catalogue repository, while contributions to the Python API and its documentation belong here.

Installation

Install xeo from PyPI:

python -m pip install xeo

Plotting is optional. Install xeo with Matplotlib support when you need it:

python -m pip install "xeo[plot]"

Or install it from conda-forge:

conda install -c conda-forge xeo

To use the current development version:

git clone https://github.com/awesome-spectral-indices/xeo.git
cd xeo
python -m pip install --editable .

xeo requires Python 3.10 or newer.

Getting started

Explore the catalogue

Import xeo to access the bundled catalogue and its instrument collection:

import xeo

print(xeo.catalogue)
print(f"Catalogue version: {xeo.catalogue.version}")
print(f"Number of instruments: {len(xeo.instruments)}")
print(list(xeo.instruments))

xeo.instruments is a frozen collection keyed by instrument identifier. Instruments support both attribute and mapping access:

msi = xeo.instruments.MSI_S2A
assert msi is xeo.instruments["MSI_S2A"]

print(msi.name)
print(msi.platform)
print(msi.operator)
print(msi.contributors)
print(msi.status)

Inspect instrument metadata

Required catalogue fields are exposed as attributes. Optional and domain-specific metadata can be discovered through extensions, while relationships connect an instrument to its family and platform companions:

print(msi.extension_names)
print(msi.extensions["spectral"].keys())
print(msi.family)
print(msi.platform_companions)
print(msi.references)

Use msi.data to inspect the original record, or msi.to_dict() when you need an independent copy that can be modified safely.

Search for instruments

Catalogue.search() returns an Instruments collection containing every match. Different properties are combined with AND, while lists mean “match any of these values”:

results = xeo.catalogue.search(
    operator=["ESA", "NASA"],
    platform_type="satellite",
    status="operational",
    has_bands=True,
)

print(list(results))

Use has_bands and has_srf to filter by spectral-data availability. For start_date, an inclusive YYYY-MM-DD/YYYY-MM-DD interval avoids requiring an exact date:

launched = xeo.catalogue.search(
    start_date="2000-01-01/2003-01-01"
)

Load spectral bands

When band definitions are available, bands() returns a DataFrame indexed by band identifier:

if msi.has_bands:
    bands = msi.bands()
    print(bands.loc[["B2", "B3", "B4"], ["center_wavelength", "bandwidth"]])

Wavelengths and bandwidths are expressed in nanometres, and band-level ground sampling distances are expressed in metres. Thermal bands may also include noise-equivalent temperature difference values in the ne_delta_t column.

Load spectral response functions

When an SRF is available, srf() returns a DataFrame with a wavelength column and one response column per band:

if msi.has_srf:
    srf = msi.srf()
    print(srf[["wavelength", "B2", "B3", "B4"]].head())

SRFs are external CSV resources. The first srf() call downloads the file into a per-user cache organized by catalogue version; subsequent calls reuse that local file and work offline. Use msi.srf(refresh=True) to replace the cached file with the current resource. Set the XEO_CACHE_DIR environment variable when the cache should live in a custom writable location.

Both bands() and srf() return None when the requested data is not available. Checking has_srf reads catalogue metadata only and never downloads anything.

Plot bands and spectral response functions

Install the optional plotting extra, then pass one instrument id, a list of ids, a dictionary selecting bands, or a list of per-instrument dictionaries:

bands_ax = xeo.plot_bands({"MSI_S2A": ["B2", "B3", "B4", "B8"]})
srf_ax = xeo.plot_srf(["MSI_S2A", "OLI_L8"], figsize=(10, 6))

Dictionary selections can attach native Matplotlib styles to individual bands:

ax = xeo.plot_srf(
    [
        {
            "MSI_S2A": [
                {"B4": {"color": "red", "linestyle": "--", "linewidth": 2}}
            ]
        },
        {"OLI_L8": [{"B5": {"color": "blue", "linewidth": 2}}]},
    ],
    title="Selected red and near-infrared responses",
)

Both functions return a Matplotlib Axes, so the complete Matplotlib API remains available for further customization.

Discover data access points

get_data_access() retrieves the catalogue entry for a provider and processing level. It defaults to the primary Google Earth Engine collection:

earth_engine = msi.get_data_access()
planetary_computer = msi.get_data_access("planetary_computer", "boa")
cdse = msi.get_data_access("cdse", "toa")

Available providers are ee, planetary_computer, cdse, and eopf; supported processing and product levels are primary, boa, toa, raw, lst, wst, grd, rtc, and slc. An available entry is returned as a dictionary with stac_endpoint, collection, and docs. Valid combinations that are not available for an instrument return None.

Work with raw catalogue data

The object API is intended for exploration, but the complete JSON-compatible catalogue is also available for custom workflows:

raw_record = xeo.catalogue.data["instruments"]["MSI_S2A"]
catalogue_copy = xeo.catalogue.to_dict()

Treat .data as read-only. Use .to_dict() when downstream code needs to modify a catalogue or instrument dictionary.

Update the local catalogue

Each xeo release includes a catalogue snapshot. To compare it with the current catalogue on GitHub and replace the local JSON file when necessary, use:

xeo.catalogue.update()

The method reports whether the catalogue was already current or was updated to a new version. A successful update refreshes xeo.catalogue and the shared xeo.instruments collection immediately. It requires an internet connection and write access to the installed xeo/data directory.

Tutorials

The tutorial notebooks provide complete, executable examples:

  1. Getting started
  2. Exploring instruments
  3. Spectral bands
  4. Spectral response functions
  5. Raw data and DataFrame workflows
  6. Data access
  7. Advanced search
  8. Plotting spectral data
  9. Updating the catalogue

Contributing

Contributions are welcome. See CONTRIBUTING.md for development setup, testing, documentation guidance, and where to propose catalogue-data changes.

License

xeo is available under the MIT License.

Funding

The pilot of this project was funded by the Climate Change AI (CCAI) Innovation Grants program, hosted by CCAI with the support of the Global Methane Hub (GMH).

Climate Change AI      Global Methane Hub