Skip to main content

strait — satellite vessel detection & port activity monitoring

A Python package for detecting vessels from Sentinel-1 SAR imagery and measuring port activity from satellite data — any port, any time.

The one thing

import strait

cutout = strait.Cutout(
    module="sentinel1",
    x=slice(103.4, 104.6),
    y=slice(1.0, 1.6),
    time=slice("2021-01", "2026-09"),
)
cutout.prepare()  # download + process scenes
detections = cutout.detect()  # CFAR vessel detection
monthly = cutout.aggregate(detections, zones={"eastern": (104.0, 1.24, 104.35, 1.40)})

That gives you monthly vessel counts per zone from free satellite radar.

Why this exists

Ports publish trade statistics with a 2-4 week lag. Satellite radar sees ships at anchor immediately, day or night, cloud or clear. This package turns that satellite data into economic indicators.

It was built for the Singapore Strait Observatory project, where radar-derived anchorage presence explains 48% of bunker sales variance (R²=0.478, detrended, weather-robust, validated against AIS).

Install

pip install strait-observatory

What it does

Layer What Output
Cutout Spatial/temporal subset + data source abstraction xarray Dataset
detect() Vessel detection (trimmed CFAR) GeoDataFrame of detections
aggregate() Zone × time aggregation Monthly/weekly/daily counts
AIS Validation against live/historical AIS Precision/recall metrics
Stats Join with official trade statistics Correlation results

Data sources

Source What Auth
Copernicus Sentinel-1 SAR radar imagery Free CDSE account
AISStream.io Live vessel AIS Free API key
AISHub.net Community AIS Free membership
Mendeley (historical) Port AIS datasets Open download
S2Coast-2023 10m coastline (land mask) Zenodo, open

Quick start

pip install strait-observatory
export CDSE_USER=your@email
export CDSE_PASSWORD=your_password
import strait

# 1. Define your area and time
cutout = strait.Cutout(
    module="sentinel1",
    x=slice(103.4, 104.6),  # longitude
    y=slice(1.0, 1.6),      # latitude
    time=slice("2021-01", "2026-09"),
)

# 2. Download and process (first time takes ~1h for 5 years)
cutout.prepare()

# 3. Detect vessels
detections = cutout.detect(method="trimmed_cfar")

# 4. Define anchorage zones (or use built-in Singapore zones)
zones = strait.Zones.singapore_strait()
monthly = cutout.aggregate(detections, zones, freq="MS")

# 5. Validate against AIS (optional)
ais = strait.AIS(source="aisstream", api_key="...")
match = ais.match(detections, threshold_m=500)

# 6. Correlate with official statistics (optional)
stats = strait.Stats.from_datagov_sg()
results = stats.correlate(monthly, target="bunker_sales")

Architecture (inspired by atlite)

strait/
├── __init__.py          # exports Cutout, detect, aggregate, AIS, Stats
├── cutout.py            # Cutout class (spatial/temporal abstraction)
├── detect/
│   ├── __init__.py      # detect() dispatcher
│   ├── cfar.py          # classic CFAR (v3.1)
│   ├── trimmed_cfar.py  # trimmed CFAR (v4, from SAR literature)
│   └── land_mask.py     # coastline-based land mask
├── data/
│   ├── __init__.py      # data source registry
│   ├── sentinel1.py     # Sentinel-1 via CDSE (Sentinel Hub + OData)
│   ├── ais.py           # AIS from multiple sources
│   └── official.py      # Official statistics (data.gov.sg, etc.)
├── aggregate.py         # zone × time aggregation
├── validate.py          # SAR-AIS matching, precision/recall
├── stats.py             # econometric correlation
└── zones.py             # built-in zone definitions

Built-in zones

# Singapore Strait (from the observatory project)
zones = strait.Zones.singapore_strait()

# Define your own
zones = strait.Zones({
    "my_anchorage": (104.0, 1.24, 104.35, 1.40),  # lon_min, lat_min, lon_max, lat_max
    "port_area": (103.68, 1.20, 104.02, 1.34),
})

License

MIT

Citation

If you use this in research, cite the Singapore Strait Observatory:

@software{strait_observatory_2026,
  title = {strait: satellite vessel detection and port activity monitoring},
  author = {Sivasubramanian, S.},
  year = {2026},
  url = {https://github.com/siva-sub/strait}
}

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

strait_observatory-0.2.0.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

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

strait_observatory-0.2.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file strait_observatory-0.2.0.tar.gz.

File metadata

  • Download URL: strait_observatory-0.2.0.tar.gz
  • Upload date:
  • Size: 19.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for strait_observatory-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2b7dbc8111fa78375ca90fcc804f8f60537eed90fa1b2f94e8c5e4d0d1e38fba
MD5 2edba207fceb5b6c1aff639fd32f598e
BLAKE2b-256 359dcf45054cba50e7b6c0a193b25e38d6242866495cce156477159b98d67791

See more details on using hashes here.

File details

Details for the file strait_observatory-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for strait_observatory-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 abf11ed751ad9c73e16917abb4fd1d3d5e6bb52a091aa46c15fb996b21e5aa25
MD5 e931123c8dc64128aa24be063ae7e0a1
BLAKE2b-256 790ac077a1134e5db9043c781dfd811355a868ebedc45d822d2fb78ca89c8107

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page