Download Esri Wayback imagery and visually validate geographic points from a CSV — dataset-agnostic, works in any remote sensing or land-cover context.
Project description
siteval
siteval downloads Esri Wayback very-high-resolution historical imagery for a list of geographic points and presents them in a clean Accept / Reject / Caution GUI for visual validation. Give it a CSV of coordinates and a target date; it samples imagery through time around each point so you can review land-cover change and confirm what's on the ground.
It is dataset-agnostic — any CSV with id, lat, lon, and a
target_date (or target_year) column works.
Use cases: land-cover validation, training-data quality control, plot-level habitat assessment, change-detection review, or any remote sensing workflow where a human needs to judge historical satellite/aerial imagery.
Two ways to use it
| Best for | |
|---|---|
Desktop app (siteval run) |
A guided 4-step window: upload → set parameters → download → validate. No command line needed. |
Command line (siteval download / siteval validate) |
Scripting, batch jobs, and reproducible pipelines. |
Installation
pip install siteval
Or from source:
git clone https://github.com/vikeshdh/siteval.git
cd siteval
pip install -e ".[dev]"
Requires Python 3.9+. Dependencies: pandas, requests, tqdm, Pillow.
tkinter powers the GUI and ships with most Python distributions
(on Linux: sudo apt-get install python3-tk).
Standalone executable (no Python required)
To build a double-clickable app for sharing with non-technical users:
pip install pyinstaller
python build_exe.py
This produces dist/siteval.exe (Windows) or dist/siteval (macOS/Linux).
Quickstart — desktop app
siteval run
A single window walks you through four steps:
- Upload CSV — pick your points file; siteval previews it and checks the schema.
- Parameters — set how far back/forward in time to sample, the interval between images, the zoom level, and the tile-grid size. A live preview shows exactly how many images each point will produce.
- Download — imagery is fetched from Esri Wayback with a progress bar.
- Validate — review each point and record Accept / Reject / Caution + notes.
Quickstart — command line
1. Prepare a CSV
siteval requires these columns:
| Column | Type | Description |
|---|---|---|
id |
string | Unique point identifier (used as folder/filename prefix) |
lat |
float | Decimal latitude, WGS84 |
lon |
float | Decimal longitude, WGS84 |
target_date |
date | Target acquisition date, YYYY-MM-DD |
target_year (integer) is also accepted for backward compatibility — it is
converted to mid-year (YYYY-07-01) automatically. Extra columns pass through
to the output unchanged.
id,lat,lon,target_date
KONZ_001,39.1008,-96.5631,2020-07-15
WOOD_002,47.1282,-99.2413,2019-06-01
See examples/test_points.csv for a ready-to-use
sample.
2. Download imagery
siteval download --csv points.csv --output imagery/ \
--back 1 --back-unit years \
--forward 1 --forward-unit years \
--interval 1 --interval-unit years
For each point, siteval samples Esri Wayback captures at a fixed interval
across a window that extends a given distance back and forward from the
target date, then picks the closest available capture to each step. Perceptual
hashing skips visually identical captures. Images are written as
imagery/<id>/<id>_<N>_<YYYY-MM-DD>.png.
The example above produces three images per point: one year before, the target date, and one year after.
3. Validate
siteval validate --csv points.csv --imagery imagery/ --output results/
A GUI opens showing each point's images side by side, with the capture date on every image. For each point:
| Key | Action |
|---|---|
A |
Mark as Accept |
R |
Mark as Reject |
C |
Mark as Caution |
Enter / Ctrl+S |
Save and advance |
← / → |
Navigate to previous / next point |
Decisions auto-save to results/validated_points.csv on exit. The validator
resumes from the first unvalidated point if you close and reopen.
Python API
from siteval import WaybackDownloader, ImageValidator
# Download imagery for all points in a CSV
downloader = WaybackDownloader(
output_dir="imagery",
zoom=18,
back_days=365, forward_days=365, interval_days=365, # 1 yr each side, yearly
tile_size=3,
)
stats = downloader.process_csv("points.csv")
print(f"Downloaded {stats['success']} / {stats['total']} points")
# Launch the validation GUI
validator = ImageValidator(
input_dir="imagery",
csv_path="points.csv",
output_path="results/validated_points.csv",
)
validator.run()
# Validate the CSV schema before processing
from siteval import load_points, REQUIRED_COLUMNS
df = load_points("my_points.csv") # raises FileNotFoundError or ValueError if invalid
CLI reference
siteval run
siteval download --csv PATH --output DIR
[--back N --back-unit days|months|years]
[--forward N --forward-unit days|months|years]
[--interval N --interval-unit days|months|years]
[--zoom 17|18|19] [--tile-size 1|3|5]
[--logs DIR] [--verbose]
siteval validate --csv PATH --imagery DIR --output DIR [--filename NAME]
siteval download --help
siteval validate --help
Parameters explained
| Parameter | What it controls |
|---|---|
| back / forward | How far before and after the target date to sample (e.g. 2 years back, 0 forward). |
| interval | The step between sampled images (e.g. every 6 months). The number of images is derived from the window ÷ interval. |
| zoom | Wayback tile zoom: 17 (~1.2 km view), 18 (~600 m), 19 (~300 m). |
| tile-size | Grid of tiles per image: 1×1 (256 px), 3×3 (768 px), 5×5 (1280 px). Larger = more surrounding context. |
Output format
validated_points.csv contains all original columns plus:
| Column | Values |
|---|---|
decision |
accept, reject, caution, or "" |
validated |
True / False |
notes |
Free-text notes from the GUI |
Examples
examples/test_points.csv— 10 sample points spanning varied land-cover types, using thetarget_dateschema.examples/filter_neon.py— filters the NEON VST non-forest reference CSV into a siteval-compatiblepoints.csv. Runs in Google Colab or locally.
python examples/filter_neon.py
Development
pip install -e ".[dev]"
pytest tests/ -v
Contributions welcome. Please open an issue before submitting a PR.
Citation
If you use siteval in published research, please cite:
Dheeriya, V. (2026). siteval: A Python toolkit for Esri Wayback imagery
download and visual validation of geographic points.
https://github.com/vikeshdh/siteval
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 siteval-0.2.0.tar.gz.
File metadata
- Download URL: siteval-0.2.0.tar.gz
- Upload date:
- Size: 32.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0801984b4fa4f92110c9311c19abc649496c192d3a7830b79673bad204a3f07e
|
|
| MD5 |
a4607507e200217be8b310c40b37e134
|
|
| BLAKE2b-256 |
5e920c73ecc738d54be4fd9d3a2c31b7d18aa9e667eaaa214c020ab37c723b46
|
Provenance
The following attestation bundles were made for siteval-0.2.0.tar.gz:
Publisher:
publish.yml on vikeshdh/siteval
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
siteval-0.2.0.tar.gz -
Subject digest:
0801984b4fa4f92110c9311c19abc649496c192d3a7830b79673bad204a3f07e - Sigstore transparency entry: 1725131902
- Sigstore integration time:
-
Permalink:
vikeshdh/siteval@f09fe4e1adca0f773b748b6a7fa1fe1847cd42b4 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vikeshdh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f09fe4e1adca0f773b748b6a7fa1fe1847cd42b4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file siteval-0.2.0-py3-none-any.whl.
File metadata
- Download URL: siteval-0.2.0-py3-none-any.whl
- Upload date:
- Size: 31.0 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 |
e6812cc955995ce6c4ce96a3f0981838483dd149c28a52a4763398058e5575b2
|
|
| MD5 |
755fc68f5fbdf3f63d30acd2d5c081fc
|
|
| BLAKE2b-256 |
b752f015a00a493a11a6920e4f2f5f14954cdc49c43295421ffa80ea27b3c7ff
|
Provenance
The following attestation bundles were made for siteval-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on vikeshdh/siteval
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
siteval-0.2.0-py3-none-any.whl -
Subject digest:
e6812cc955995ce6c4ce96a3f0981838483dd149c28a52a4763398058e5575b2 - Sigstore transparency entry: 1725132029
- Sigstore integration time:
-
Permalink:
vikeshdh/siteval@f09fe4e1adca0f773b748b6a7fa1fe1847cd42b4 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vikeshdh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f09fe4e1adca0f773b748b6a7fa1fe1847cd42b4 -
Trigger Event:
push
-
Statement type: