Metadata-Version: 2.4
Name: sen2p
Version: 0.2.0
Summary: Download Sentinel-2 data from Microsoft Planetary Computer
Home-page: https://github.com/tnmthai/sen2p
Author: Thai Tran
Author-email: ThaiTran@outlook.co.nz
License: MIT
Project-URL: Homepage, https://github.com/tnmthai/sen2p
Project-URL: Issues, https://github.com/tnmthai/sen2p/issues
Project-URL: PyPI, https://pypi.org/project/sen2p/
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: planetary-computer
Requires-Dist: pystac-client
Requires-Dist: rioxarray
Requires-Dist: xarray
Requires-Dist: tqdm
Requires-Dist: geopandas
Requires-Dist: shapely
Requires-Dist: rasterio
Requires-Dist: pandas
Dynamic: author-email
Dynamic: home-page
Dynamic: requires-python

# sen2p

**sen2p** is a lightweight Python library to search, download, and manage Sentinel-2 imagery from [Microsoft Planetary Computer](https://planetarycomputer.microsoft.com/). No API keys required.

Focused on **data discovery + download + satellite utilities**. For raster processing and analysis, use [rasteric](https://pypi.org/project/rasteric/).

## Installation

```bash
pip install sen2p
```

## Requirements

- **Python** >= 3.9

## Features

- 🔍 Search with cloud cover and date filtering
- 🏆 Auto-select best image (low cloud, good coverage, nearest date)
- 📍 Find nearest image to a specific date
- 🛰️ Download selected bands with friendly aliases (`blue`, `nir`, etc.)
- 📦 Auto-merge bands into single GeoTIFF
- ⚡ Parallel download (`workers=N`)
- 🔄 Retry with exponential backoff
- ♻️ Skip existing files
- 📊 Export metadata to CSV / footprints to GeoJSON
- 📅 Timeline visualization
- 🖥️ CLI: `sen2p search`, `sen2p download`, `sen2p best`, `sen2p nearest`, `sen2p bandinfo`, `sen2p bands`

## Quick Start

### Python

```python
from sen2p import search, best_item, nearest, download, bandinfo, bands, timeline, preview, meta_df, export_meta

# Search
items = search("2023-06-01", "2023-06-30", [172.1, -43.5], cloud_max=20)
print(f"Found {len(items)} items")

# Timeline
timeline(items)

# Best image (lowest cloud, best coverage, nearest date)
item = best_item("2023-06-01", "2023-06-30", [172.1, -43.5])
preview(item)

# Nearest to a specific date
item = nearest("2023-06-15", [172.1, -43.5], cloud_max=20)

# Download with friendly band names
results = download(
    start_date="2023-06-01",
    end_date="2023-06-30",
    location=[172.1, -43.5],
    bands=["blue", "green", "red", "nir"],
    output_dir="output",
    cloud_max=20,
    workers=4,
)

# Export metadata
df = meta_df(items)
export_meta(items, "metadata.csv")

# Band info
info = bandinfo("nir")
# {'band': 'B08', 'name': 'NIR', 'resolution': '10m', 'wavelength': '842nm'}
```

### CLI

```bash
# Search
sen2p search --start 2023-06-01 --end 2023-06-30 --location "172.1,-43.5" --cloud-max 20

# Best image
sen2p best --start 2023-06-01 --end 2023-06-30 --location "172.1,-43.5"

# Nearest to date
sen2p nearest --date 2023-06-15 --location "172.1,-43.5" --cloud-max 20

# Download with parallel workers
sen2p download --start 2023-06-01 --end 2023-06-10 --location "172.1,-43.5" \
    --bands blue,green,red,nir --output output --cloud-max 20 --workers 4

# Band info
sen2p bandinfo nir
sen2p bands

# Raster metadata
sen2p meta output/S2B_..._merged.tif
```

## Location Formats

```python
[172.1, -43.5]                              # Point [lon, lat]
[172.0, -43.6, 172.5, -43.3]               # Bounding box
"study_area.shp"                            # Shapefile path
"area.geojson"                              # GeoJSON file path
{"type": "Point", "coordinates": [172.1, -43.5]}  # GeoJSON dict
```

## Band Aliases

Use friendly names instead of band codes:

| Alias | Band | Resolution | Wavelength |
|---|---|---|---|
| `coastal` | B01 | 60m | 443nm |
| `blue` | B02 | 10m | 490nm |
| `green` | B03 | 10m | 560nm |
| `red` | B04 | 10m | 665nm |
| `rededge1` | B05 | 20m | 705nm |
| `rededge2` | B06 | 20m | 740nm |
| `rededge3` | B07 | 20m | 783nm |
| `nir` | B08 | 10m | 842nm |
| `nir08` | B8A | 20m | 865nm |
| `swir1` | B11 | 20m | 1610nm |
| `swir2` | B12 | 20m | 2190nm |

```python
from sen2p import bandinfo, bands

bandinfo("nir")  # {'band': 'B08', 'name': 'NIR', 'resolution': '10m', 'wavelength': '842nm'}
bands()          # Full dict of all bands
```

## Functions

### Search & Discovery

| Function | Description |
|---|---|
| `search(start, end, location, ...)` | Search for items with filters |
| `best_item(start, end, location, ...)` | Auto-select best image (cloud + coverage + date) |
| `nearest(date, location, ...)` | Find image closest to a specific date |
| `collections()` | List available STAC collections |

### Download

| Function | Description |
|---|---|
| `download(start, end, location, bands, ...)` | Download with parallel workers and retry |

### Metadata

| Function | Description |
|---|---|
| `meta_df(items)` | Convert items to pandas DataFrame |
| `export_meta(items, output)` | Export metadata to CSV |
| `export_footprint(items, output)` | Export footprints to GeoJSON |
| `show_meta(file_path)` | Display raster file metadata |

### Visualization

| Function | Description |
|---|---|
| `preview(item)` | Quick text preview of an item |
| `timeline(items)` | Text timeline with cloud cover bars |

### Band Utilities

| Function | Description |
|---|---|
| `bandinfo(band)` | Get band metadata (name, resolution, wavelength) |
| `bands()` | List all Sentinel-2 bands |
| `resolve_band_names(aliases)` | Convert friendly names to STAC keys |

## Integration with rasteric

```python
from sen2p import download
from rasteric import ndvi, clip, plot

# Download
results = download(
    start_date="2023-06-01", end_date="2023-06-10",
    location=[172.1, -43.5], bands=["red", "nir"],
    output_dir="data", cloud_max=20,
)

# Process with rasteric
ndvi(results[0]["merged"], "ndvi.tif", red_band=1, nir_band=2)
clip("ndvi.tif", "boundary.shp", "ndvi_clipped.tif")
plot("ndvi_clipped.tif", bands=(1,), cmap="RdYlGn", title="NDVI")
```

## Contributing

- **Repository**: [github.com/tnmthai/sen2p](https://github.com/tnmthai/sen2p)
- **Issues**: [github.com/tnmthai/sen2p/issues](https://github.com/tnmthai/sen2p/issues)
- **PyPI**: [pypi.org/project/sen2p](https://pypi.org/project/sen2p/)

## License

MIT License
