Python package to download and process vegetation products from WEkEO (HR-VPP) and CDSE (Sentinel-2)
Project description
PyVPP
Python package to download and preprocess vegetation products from Copernicus services:
- HR-VPP (High Resolution Vegetation Phenology and Productivity) via WEkEO
- Sentinel-2 L2A raw data via CDSE (Copernicus Data Space Ecosystem)
⚠️ IMPORTANT - VPP_Index Dataset Currently Unavailable (January 2025)
The VPP_Index dataset (EO:EEA:DAT:CLMS_HRVPP_VI) currently returns 404 errors on WEkEO.
This dataset, which contained daily vegetation indices (LAI, FAPAR, NDVI, PPI), appears to have been discontinued or moved since 2024.
✅ Datasets that ARE working:
VPP_ST(Seasonal Trajectories): Contains PPI, QFLAGVPP_Pheno(Phenology & Productivity): Contains SOSD, MAXD, EOSD, LENGTH, AMPL, TPROD, etc.
🔧 If you needed VPP_Index:
- For PPI → Use
VPP_ST - For phenology parameters → Use
VPP_Pheno - For LAI, FAPAR, NDVI → Currently not available via PyVPP (see alternatives below)
See DATASETS_AVAILABLE.md for more details.
Installation
pip install pyvpp
Quick Start
PyVPP supports two main workflows:
A. HR-VPP Products (WEkEO)
1. Configure your WEkEO credentials
import pyvpp
# Create .hdarc file with your credentials
pyvpp.create_hdarc("your_wekeo_username", "your_wekeo_password")
2. Download HR-VPP data
Phenology parameters (RECOMMENDED - WORKING)
import pyvpp
# Download phenology parameters (annual products)
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno', # ✅ Working
shape='path/to/your/area.shp', # or DEIMS ID
dates=['2020-01-01', '2020-12-31'],
products=['SOSD', 'MAXD', 'EOSD', 'LENGTH']
)
downloader.run()
Seasonal Trajectories - PPI (RECOMMENDED - WORKING)
import pyvpp
# Download PPI (Plant Phenology Index) every 10 days
downloader = pyvpp.wekeo_download(
dataset='VPP_ST', # ✅ Working
shape='path/to/your/area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['PPI', 'QFLAG']
)
downloader.run()
Vegetation Indices (⚠️ CURRENTLY NOT AVAILABLE)
import pyvpp
# ⚠️ WARNING: This dataset is currently returning 404 errors
# VPP_Index (LAI, FAPAR, NDVI) is not available as of January 2025
downloader = pyvpp.wekeo_download(
dataset='VPP_Index', # ⚠️ Returns 404 error
shape='path/to/your/area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['LAI', 'FAPAR'] # Not available
)
# This will fail with: 404 Client Error
B. Sentinel-2 Raw Data (CDSE)
New in v0.4.0: Download Sentinel-2 L2A products directly from CDSE.
1. Configure CDSE credentials
You have three options:
Option 1: Configuration file (recommended)
mkdir -p ~/.pyvpp
cat > ~/.pyvpp/config.toml << EOF
[cdse]
user = "your_email@example.com"
password = "your_password"
EOF
Option 2: Environment variables
export CDSE_USER="your_email@example.com"
export CDSE_PASSWORD="your_password"
Option 3: Direct in code
from pyvpp.cdse import load_cdse_credentials
# Credentials passed directly to CDSEDownload
Register at: https://dataspace.copernicus.eu/
2. Download Sentinel-2 data
L2A - Bottom of Atmosphere (Default - Atmospherically Corrected)
from pyvpp import CDSEDownload
# Download Sentinel-2 L2A products (recommended for most use cases)
downloader = CDSEDownload(
shape='path/to/your/area.shp', # or DEIMS ID
dates=('2023-06-01', '2023-06-30'),
bands=['B04', 'B08'], # Red, NIR
outdir='sentinel2_data',
processing_level='L2A', # Default: atmospherically corrected
utm_zone='30T' # Optional: filter by UTM zone
)
# Run full pipeline: search -> download -> mosaic -> clip
downloader.run()
L1C - Top of Atmosphere (No Atmospheric Correction - for ACOLITE, etc.)
from pyvpp import CDSEDownload
# Download Sentinel-2 L1C products (TOA reflectance)
# Useful for custom atmospheric correction (ACOLITE, Sen2Cor, etc.)
downloader = CDSEDownload(
shape='path/to/your/area.shp',
dates=('2023-06-01', '2023-06-30'),
bands=['B04', 'B08'],
outdir='sentinel2_L1C',
processing_level='L1C' # Top of Atmosphere
)
downloader.run()
Output: one mosaic per requested band per acquisition date, organized
in subfolders <outdir>/YYYYMMDD_s2msi/. Files are named
YYYYMMDD_s2msi_<alias>.tif (e.g. 20230610_s2msi_b04_red.tif).
Each band is delivered in its native resolution (10 m or 20 m);
the SCL band keeps its uint8 dtype.
Processing Level Comparison:
L2A(default): Bottom of Atmosphere - atmospherically corrected, ready for analysisL1C: Top of Atmosphere - raw reflectance, use for custom atmospheric correction with tools like ACOLITE
Available Sentinel-2 bands
Reflectance bands (any combination of resolutions can be requested in a single call):
| Band | Alias | Resolution | Description |
|---|---|---|---|
B02 |
b02_blue |
10 m | Blue |
B03 |
b03_green |
10 m | Green |
B04 |
b04_red |
10 m | Red |
B08 |
b08_nir |
10 m | NIR (broad, 842 nm) |
B01 |
b01_coastal |
20 m | Coastal aerosol |
B05 |
b05_re1 |
20 m | Red-edge 1 |
B06 |
b06_re2 |
20 m | Red-edge 2 |
B07 |
b07_re3 |
20 m | Red-edge 3 |
B8A |
b8a_nir |
20 m | NIR (narrow, 865 nm) |
B11 |
b11_swir1 |
20 m | SWIR 1 |
B12 |
b12_swir2 |
20 m | SWIR 2 |
Cloud / scene-classification mask (L2A only):
| Band | Alias | Resolution | Description |
|---|---|---|---|
SCL |
scl |
20 m | Sen2Cor Scene Classification Layer (categorical) |
Example use cases:
# NDVI calculation
CDSEDownload(shape='area.shp', dates=('2023-01-01', '2023-12-31'), bands=['B04', 'B08'])
# RGB visualization
CDSEDownload(shape='area.shp', dates=('2023-01-01', '2023-12-31'), bands=['B02', 'B03', 'B04'])
# Water mask / turbidity (mixes 10 m + 20 m + categorical SCL)
CDSEDownload(
shape='area.shp',
dates=('2023-01-01', '2023-12-31'),
bands=['B02', 'B03', 'B04', 'B08', 'B11', 'B12', 'SCL'],
)
Available Datasets & Products
✅ VPP_Pheno (Vegetation Phenology & Productivity)
Status: Working
Products:
- SOSD (Start of Season Date)
- EOSD (End of Season Date)
- MAXD (Maximum Date)
- MINV (Minimum Value)
- MAXV (Maximum Value)
- AMPL (Amplitude)
- LENGTH (Length of Season)
- LSLOPE (Left Slope)
- RSLOPE (Right Slope)
- SPROD (Seasonal Productivity)
- TPROD (Total Productivity)
- SOSV (Start of Season Value)
- EOSV (End of Season Value)
✅ VPP_ST (Seasonal Trajectories)
Status: Working
Products:
- PPI (Plant Phenology Index)
- QFLAG (Quality Flag)
⚠️ VPP_Index (Vegetation Indices)
Status: NOT AVAILABLE (404 Error as of January 2025)
Products (no longer accessible):
LAI (Leaf Area Index)FAPAR (Fraction of Absorbed Photosynthetically Active Radiation)NDVI (Normalized Difference Vegetation Index)PPI (now available in VPP_ST)
✅ SLSTR (Sentinel-3 Land Surface Temperature)
Status: Working
Products: SL_2_LST___
Using DEIMS IDs
You can use DEIMS site IDs instead of shapefiles:
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno',
shape='deimsid:https://deims.org/bcbc866c-3f4f-47a8-bbbc-0a93df6de7b2',
dates=['2020-01-01', '2020-12-31'],
products=['SOSD', 'MAXD']
)
Step-by-step workflow
PyVPP performs the following operations:
- Downloads all Sentinel-2 tiles that intersect your area of interest
- Filters tiles by UTM zone
- Creates mosaics for each date and product
- Clips mosaics to your exact boundaries
- Saves final products as
mosaic_YYYYMMDD_PRODUCT_rec.tif - Cleans up intermediate files
Advanced Usage
Use credentials directly (without .hdarc)
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno',
shape='area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['SOSD'],
user='your_username', # Direct credentials
password='your_password'
)
Clean old .hdarc format
If you have an old .hdarc file (pre-March 2024):
import pyvpp
pyvpp.clean_old_hdarc() # Removes obsolete 'url:' line
Step-by-step execution
# Execute steps individually
downloader.download() # Only download
downloader.mosaic_and_clip() # Only mosaic and clip
downloader.clean() # Only clean intermediate files
Alternatives for LAI, FAPAR, NDVI
Since VPP_Index is currently unavailable, here are alternatives:
1. Google Earth Engine (Recommended)
// Calculate NDVI from Sentinel-2
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
.filterDate('2020-01-01', '2020-12-31')
.filterBounds(geometry);
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
return image.addBands(ndvi);
};
2. Sentinel Hub
- Pre-computed LAI, FAPAR, NDVI available
3. Copernicus Global Land Service
https://land.copernicus.eu/global/products/
- 300m resolution (not 10m like HR-VPP)
4. Calculate from Sentinel-2 directly
import rasterio
import numpy as np
# NDVI = (NIR - Red) / (NIR + Red)
with rasterio.open('sentinel2.tif') as src:
red = src.read(4) # Band 4
nir = src.read(8) # Band 8
ndvi = (nir - red) / (nir + red)
Troubleshooting
Error 404: Dataset not found
If you get a 404 error with VPP_Index:
requests.exceptions.HTTPError: 404 Client Error: Not Found for url:
https://gateway.prod.wekeo2.eu/hda-broker/api/v1/datasets/EO:EEA:DAT:CLMS_HRVPP_VI
Solution: Use VPP_Pheno or VPP_ST instead (see examples above).
Authentication failed
# Recreate your .hdarc file
import pyvpp
pyvpp.create_hdarc("username", "password")
No matches found
This usually means:
- Date range is outside available data
- Area of interest has no coverage
- Product name is misspelled
Check the official documentation for data availability.
Requirements
- Python >= 3.9
- requests >= 2.28
- geopandas >= 0.12
- rasterio >= 1.3
- pyproj >= 3.4
- shapely >= 1.8
- deims >= 3.1
- fiona >= 1.8.20
- hda >= 2.18 (for WEkEO only)
Documentation & Support
- HR-VPP Documentation: https://land.copernicus.eu/pan-european/biophysical-parameters/high-resolution-vegetation-phenology-and-productivity
- WEkEO Help Center: https://help.wekeo.eu/
- PyVPP Repository: https://github.com/Digdgeo/PyVPP
- Report Issues: https://github.com/Digdgeo/PyVPP/issues
Citation
If you use PyVPP in your research, please cite:
García-Díaz, D. (2025). PyVPP: Python package for HR-VPP data access and processing.
https://github.com/Digdgeo/PyVPP
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Changelog
v1.0.0 (Current)
- Per-date output: mosaics organized in
YYYYMMDD_s2msi/subfolders, one per acquisition date - Landsat-style naming:
YYYYMMDD_s2msi_<alias>.tif(e.g.20230610_s2msi_b04_red.tif) - Red-edge bands: B05, B06, B07, B8A now fully supported
- Token auto-refresh: prevents
401 Unauthorizedon long download sessions - Resume support: already-extracted SAFE directories are skipped on re-run
- geopandas >= 0.14 required (fixes fiona 1.10+ compatibility)
v0.4.0
- Added CDSE (Copernicus Data Space Ecosystem) support for Sentinel-2 L2A/L1C
- New module
pyvpp.cdsewithCDSEDownloadclass - Multi-resolution support (10 m + 20 m + SCL in a single call)
- Per-band output files in native resolution
- Authentication via config file, env vars, or direct credentials
v0.1.9
- Fixed
.hdarcformat for HDA API v2.18+ - Added
create_hdarc(),clean_old_hdarc(),delete_hdarc()helpers
Last updated: May 2026 Status: VPP_ST ✅ | VPP_Pheno ✅ | VPP_Index ⚠️ (unavailable) | CDSE Sentinel-2 ✅
Project details
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 pyvpp-1.0.0.tar.gz.
File metadata
- Download URL: pyvpp-1.0.0.tar.gz
- Upload date:
- Size: 20.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf5d909575dab7393e084547f071ccd6b96b70d53c3d9d65f3a898bac2131211
|
|
| MD5 |
7dde3dc98cb71203218c27aefc5e969d
|
|
| BLAKE2b-256 |
bb2519dc40716db05d414c0d05c541576b267281510231c5c80c28758579cdca
|
Provenance
The following attestation bundles were made for pyvpp-1.0.0.tar.gz:
Publisher:
publish-pypi.yml on Digdgeo/PyVPP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyvpp-1.0.0.tar.gz -
Subject digest:
cf5d909575dab7393e084547f071ccd6b96b70d53c3d9d65f3a898bac2131211 - Sigstore transparency entry: 1448939350
- Sigstore integration time:
-
Permalink:
Digdgeo/PyVPP@6107022f465954049e2f028e4c24d5722d80531c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Digdgeo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@6107022f465954049e2f028e4c24d5722d80531c -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyvpp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pyvpp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
258a06d60d77dfeef2d397d358a2ea3a413bbea7aed93f4df9ffacbfa4e966ec
|
|
| MD5 |
80a4e3d62f5ec2ffc51d23a77c857a32
|
|
| BLAKE2b-256 |
49ab74de88f4e60ac99d06e8e65530ad22ea9d76276cec357e544e3fb2284992
|
Provenance
The following attestation bundles were made for pyvpp-1.0.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on Digdgeo/PyVPP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyvpp-1.0.0-py3-none-any.whl -
Subject digest:
258a06d60d77dfeef2d397d358a2ea3a413bbea7aed93f4df9ffacbfa4e966ec - Sigstore transparency entry: 1448939435
- Sigstore integration time:
-
Permalink:
Digdgeo/PyVPP@6107022f465954049e2f028e4c24d5722d80531c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Digdgeo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@6107022f465954049e2f028e4c24d5722d80531c -
Trigger Event:
push
-
Statement type: