Comparison & validation¶
Compare gridded sources¶
Available as climate_toolkit.compare_climate_sources.
climate_toolkit.compare_datasets.compare_datasets.compare_sources ¶
compare_sources(
sources,
lat=None,
lon=None,
start=None,
end=None,
input_file=None,
output_dir="./outputs",
nex_model=None,
nex_scenario="ssp245",
nex_models=None,
precip_source=None,
temp_source=None,
workers=1,
)
Fetch one or more climate datasets for a location and prepare them for comparison.
For each requested source, this function fetches cleaned, analysis-ready
daily data for a single point (latitude/longitude) over a date range via
the toolkit's preprocessing pipeline, exports each dataset to
<output_dir>/<source>.csv, and returns the datasets keyed by source
name. The returned dictionary is the input expected by print_report,
which produces the comparison tables (annual time series, annual
statistics, monthly climatologies, pairwise correlations) and PNG plots.
Climate sources retrieve daily precipitation, maximum temperature, and
minimum temperature. The soil_grid source instead retrieves static
soil properties (pH, texture fractions, bulk density, organic carbon,
CEC), broadcast as a constant daily series across the date range so it
can sit alongside the climate sources. Sources that fail to fetch are
skipped with a printed warning rather than aborting the run.
Most sources are read from Google Earth Engine and require prior Earth
Engine authentication plus a Google Cloud project id in the
GCP_PROJECT_ID environment variable (GOOGLE_CLOUD_PROJECT or
EE_PROJECT_ID also work). nasa_power uses NASA's public web
service and needs no authentication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sources
|
list of str
|
Dataset keys to fetch and compare. Valid keys: |
required |
lat
|
float
|
Latitude of the point of interest in decimal degrees (default
|
None
|
lon
|
float
|
Longitude of the point of interest in decimal degrees (default
|
None
|
start
|
str
|
Start date as |
None
|
end
|
str
|
End date as |
None
|
input_file
|
str
|
Path to a CSV of already-fetched daily data containing a |
None
|
output_dir
|
str
|
Directory where per-source CSV files are written; created if it
does not exist (default |
'./outputs'
|
nex_model
|
str
|
Single NEX-GDDP-CMIP6 model name, e.g. |
None
|
nex_scenario
|
str
|
NEX-GDDP-CMIP6 emissions scenario (default |
'ssp245'
|
nex_models
|
list of str
|
Two or more NEX-GDDP-CMIP6 model names to average into a single
ensemble-mean series (default |
None
|
precip_source
|
str
|
Precipitation partner for the |
None
|
temp_source
|
str
|
Temperature partner for the |
None
|
workers
|
int
|
Number of parallel workers for chunked Google Earth Engine fetches
(default |
1
|
Returns:
| Type | Description |
|---|---|
dict of str to pandas.DataFrame
|
Mapping from result key to a daily DataFrame with a |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a source key is unknown, |
RuntimeError
|
If none of the requested sources returned usable data. |
Examples:
Compare AgERA5 and NASA POWER for Nairobi over 2020, then print the comparison report:
>>> import climate_toolkit as ct
>>> results = ct.compare_climate_sources(
... sources=["agera_5", "nasa_power"],
... lat=-1.286,
... lon=36.817,
... start="2020-01-01",
... end="2020-12-31",
... output_dir="./outputs",
... )
>>> sorted(results)
['agera_5', 'nasa_power']
>>> from climate_toolkit.compare_datasets.compare_datasets import print_report
>>> stats = print_report(results, output_dir="./outputs")
Download station data¶
Available as climate_toolkit.download_station_data.
climate_toolkit.weather_station.download.download_station_data ¶
download_station_data(
*,
station_source,
station_coord,
date_from,
date_to,
variables=None,
station_id=None,
stage="preprocessed",
verbose=True,
cache_dir=None,
refresh_cache=False,
selection_mode="auto",
max_distance_km=DEFAULT_MAX_DISTANCE_KM,
target_elevation_m=None,
max_elevation_diff_m=DEFAULT_MAX_ELEVATION_DIFF_M,
min_completeness_ratio=DEFAULT_MIN_COMPLETENESS_RATIO,
candidate_limit=DEFAULT_CANDIDATE_LIMIT,
score_limit=DEFAULT_SCORE_LIMIT,
auto_select="auto-1",
auto_anchor_elevation=True,
disable_completeness_guard=False,
max_auto_stations=DEFAULT_MAX_AUTO_STATIONS,
custom_station_file=None,
custom_station_name=None,
custom_temp_unit="c",
custom_precip_unit="mm",
)
Download daily weather-station observations near a point of interest.
Finds weather stations close to station_coord, ranks them by
distance, elevation similarity, and data completeness, then downloads
daily observations for the requested date range and variables. All
arguments are keyword-only. The result is a pandas DataFrame (the
Python analogue of an R data.frame), with one row per
station-day, or -- when selection_mode="list" -- one row per
candidate station.
Station backends (GHCN-Daily and GSOD) are public NOAA archives and
need no Google Earth Engine authentication. The only optional
Earth Engine touchpoint is the DEM elevation lookup used when
auto_anchor_elevation=True; if Earth Engine is not configured the
lookup fails gracefully, a warning is printed, and station selection
proceeds without the elevation guard.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_source
|
str
|
Station backend to search. Valid values:
|
required |
station_coord
|
tuple of float
|
|
required |
date_from
|
date
|
First day of the requested period (inclusive). |
required |
date_to
|
date
|
Last day of the requested period (inclusive). |
required |
variables
|
list of ClimateVariable or list of str
|
Variables to request, e.g.
|
None
|
station_id
|
str
|
Explicit station identifier. Required when
|
None
|
stage
|
str
|
Processing stage of the returned data: |
'preprocessed'
|
verbose
|
bool
|
If |
True
|
cache_dir
|
str
|
Directory for cached downloads. |
None
|
refresh_cache
|
bool
|
If |
False
|
selection_mode
|
str
|
How stations are chosen. Valid values:
|
'auto'
|
max_distance_km
|
float
|
Search radius around |
DEFAULT_MAX_DISTANCE_KM
|
target_elevation_m
|
float
|
Reference elevation (m) for the elevation guard. |
None
|
max_elevation_diff_m
|
float
|
Maximum allowed absolute elevation difference (m) between a
candidate station and the target elevation. Default |
DEFAULT_MAX_ELEVATION_DIFF_M
|
min_completeness_ratio
|
float
|
Minimum fraction (0-1) of days with data required per requested
variable for a candidate to pass the completeness guard. Default
|
DEFAULT_MIN_COMPLETENESS_RATIO
|
candidate_limit
|
int
|
Maximum number of candidates retained after ranking. Default
|
DEFAULT_CANDIDATE_LIMIT
|
score_limit
|
int
|
Maximum number of nearby stations scored for completeness (the
expensive step). Default |
DEFAULT_SCORE_LIMIT
|
auto_select
|
str
|
How many top-ranked stations to download in
|
'auto-1'
|
auto_anchor_elevation
|
bool
|
If |
True
|
disable_completeness_guard
|
bool
|
If |
False
|
max_auto_stations
|
int
|
Hard cap on stations downloaded via |
DEFAULT_MAX_AUTO_STATIONS
|
custom_station_file
|
str
|
Path to a custom station CSV/JSON file. Required when
|
None
|
custom_station_name
|
str
|
Label for the custom station. Default |
None
|
custom_temp_unit
|
str
|
Temperature unit in the custom file: |
'c'
|
custom_precip_unit
|
str
|
Precipitation unit in the custom file: |
'mm'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Structure depends on
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
Download 2020 daily records from the single best GHCN-Daily station within 50 km of Nairobi:
>>> from datetime import date
>>> import climate_toolkit as ct
>>> obs = ct.download_station_data(
... station_source="ghcn_daily",
... station_coord=(-1.286, 36.817),
... date_from=date(2020, 1, 1),
... date_to=date(2020, 12, 31),
... variables=["precipitation", "max_temperature", "min_temperature"],
... selection_mode="auto",
... auto_select="auto-1",
... )
>>> obs[["date", "station_id", "precipitation", "max_temperature"]].head()
Validate grids against stations¶
Available as climate_toolkit.compare_station_to_grids.
climate_toolkit.weather_station.compare.compare_station_to_grids ¶
compare_station_to_grids(
*,
station_source,
station_coord,
date_from,
date_to,
grid_sources,
variables=None,
station_id=None,
selection_mode="auto",
selection_strategy=DEFAULT_SELECTION_STRATEGY,
auto_select="auto-1",
max_distance_km=50.0,
target_elevation_m=None,
max_elevation_diff_m=500.0,
min_completeness_ratio=0.7,
candidate_limit=10,
score_limit=25,
auto_anchor_elevation=True,
disable_completeness_guard=False,
max_auto_stations=10,
cache_dir=None,
refresh_cache=False,
precip_source=None,
temp_source=None,
wet_day_threshold_mm=DEFAULT_WET_DAY_THRESHOLD_MM,
min_overlap_days=DEFAULT_MIN_OVERLAP_DAYS,
verbose=True,
custom_station_file=None,
custom_station_name=None,
custom_temp_unit="c",
custom_precip_unit="mm",
candidate_report_prefix=None,
workers=1,
)
Validate gridded climate products against nearby station observations.
Downloads daily station records near station_coord (via
:func:download_station_data), fetches each requested gridded
product at the station location for the same period, matches the two
on date, and computes agreement statistics (bias, MAE, RMSE,
correlation) per station, grid source, and variable at daily,
monthly, seasonal, and annual timescales. For precipitation it adds
wet-day occurrence skill (hit rate, false-alarm ratio, critical
success index, frequency bias), totals, upper-tail quantiles, and
heavy-rain indices (rx1day, rx5day, R10mm, R20mm). All arguments are
keyword-only. The result is a plain Python dict (the analogue of
an R named list), ready for json.dumps or conversion of its list
entries to DataFrames.
Authentication note: the station side (GHCN-Daily / GSOD) downloads
from public NOAA archives and needs no Google Earth Engine
credentials, but most grid sources (agera_5, era_5,
chirps, chirts, imerg, terraclimate, ...) are fetched
through Google Earth Engine and require the GCP_PROJECT_ID
environment variable (or GOOGLE_CLOUD_PROJECT /
EE_PROJECT_ID) plus an authenticated Earth Engine account.
nasa_power uses the NASA POWER web API and does not need Earth
Engine. Failed grid fetches do not abort the run; they are recorded
under "grid_failures" in the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_source
|
str
|
Station backend: |
required |
station_coord
|
tuple of float
|
|
required |
date_from
|
date
|
First day of the comparison period (inclusive). |
required |
date_to
|
date
|
Last day of the comparison period (inclusive). |
required |
grid_sources
|
list of str
|
Historical gridded products to evaluate. Valid values:
|
required |
variables
|
list of ClimateVariable or list of str
|
Variables to compare. |
None
|
station_id
|
str
|
Explicit station identifier; used with
|
None
|
selection_mode
|
str
|
Station-selection behaviour: |
'auto'
|
selection_strategy
|
str
|
How stations map to variables:
|
DEFAULT_SELECTION_STRATEGY
|
auto_select
|
str
|
Number of top-ranked stations used when |
'auto-1'
|
max_distance_km
|
float
|
Station search radius in km. Default |
50.0
|
target_elevation_m
|
float
|
Reference elevation (m) for the elevation guard; |
None
|
max_elevation_diff_m
|
float
|
Maximum station-vs-anchor elevation difference (m). Default
|
500.0
|
min_completeness_ratio
|
float
|
Minimum per-variable data completeness (0-1) for candidate
stations. Default |
0.7
|
candidate_limit
|
int
|
Maximum candidates retained after ranking. Default |
10
|
score_limit
|
int
|
Maximum nearby stations scored for completeness. Default |
25
|
auto_anchor_elevation
|
bool
|
If |
True
|
disable_completeness_guard
|
bool
|
If |
False
|
max_auto_stations
|
int
|
Hard cap on stations used via |
10
|
cache_dir
|
str
|
Directory for cached downloads. Default |
None
|
refresh_cache
|
bool
|
If |
False
|
precip_source
|
str
|
Precipitation and temperature products combined when
|
None
|
temp_source
|
str
|
Precipitation and temperature products combined when
|
None
|
wet_day_threshold_mm
|
float
|
Daily precipitation (mm) at or above which a day counts as wet
in the occurrence-skill statistics. Default |
DEFAULT_WET_DAY_THRESHOLD_MM
|
min_overlap_days
|
int
|
Minimum station-grid overlap (days) below which a low-confidence
warning is attached to a metric row. Default |
DEFAULT_MIN_OVERLAP_DAYS
|
verbose
|
bool
|
If |
True
|
custom_station_file
|
str
|
Path to a custom station CSV/JSON (with
|
None
|
custom_station_name
|
str
|
Label for the custom station. Default |
None
|
custom_temp_unit
|
str
|
Temperature unit in the custom file: |
'c'
|
custom_precip_unit
|
str
|
Precipitation unit in the custom file: |
'mm'
|
candidate_report_prefix
|
str
|
If given, write a candidate-review report to
|
None
|
workers
|
int
|
Parallel workers for grid-data fetching. Default |
1
|
Returns:
| Type | Description |
|---|---|
dict
|
A report dictionary. Main keys:
With |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
RuntimeError
|
If no station observations are available for comparison. |
Examples:
Compare the best GHCN-Daily station near Nairobi against AgERA5 for
2020 (requires GCP_PROJECT_ID to be set for the grid fetch):
>>> from datetime import date
>>> import climate_toolkit as ct
>>> report = ct.compare_station_to_grids(
... station_source="ghcn_daily",
... station_coord=(-1.286, 36.817),
... date_from=date(2020, 1, 1),
... date_to=date(2020, 12, 31),
... grid_sources=["agera_5"],
... variables=["precipitation", "max_temperature", "min_temperature"],
... )
>>> import pandas as pd
>>> pd.DataFrame(report["metrics"])[
... ["grid_source", "variable", "overlap_days", "bias", "correlation"]
... ]