climate-toolkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- climate_toolkit/__init__.py +109 -0
- climate_toolkit/_resources.py +45 -0
- climate_toolkit/calculate_hazards/__init__.py +14 -0
- climate_toolkit/calculate_hazards/crop_water_balance_params.json +58 -0
- climate_toolkit/calculate_hazards/ensemble_hazards.py +1317 -0
- climate_toolkit/calculate_hazards/hazards.py +3272 -0
- climate_toolkit/cli.py +89 -0
- climate_toolkit/climate_statistics/__init__.py +14 -0
- climate_toolkit/climate_statistics/ensemble_statistics.py +1065 -0
- climate_toolkit/climate_statistics/statistics.py +3375 -0
- climate_toolkit/climatology/__init__.py +104 -0
- climate_toolkit/climatology/_cli_common.py +172 -0
- climate_toolkit/climatology/heat_stress.py +675 -0
- climate_toolkit/climatology/human_heat_stress.py +389 -0
- climate_toolkit/climatology/long_term_climatology.py +1939 -0
- climate_toolkit/climatology/spei.py +745 -0
- climate_toolkit/climatology/vpd.py +246 -0
- climate_toolkit/climatology/xclim_reference.py +988 -0
- climate_toolkit/compare_datasets/__init__.py +14 -0
- climate_toolkit/compare_datasets/compare_datasets.py +1070 -0
- climate_toolkit/compare_periods/__init__.py +14 -0
- climate_toolkit/compare_periods/ensemble_periods.py +2899 -0
- climate_toolkit/compare_periods/periods.py +1892 -0
- climate_toolkit/crop_calendar/__init__.py +94 -0
- climate_toolkit/crop_calendar/ggcmi.py +198 -0
- climate_toolkit/crop_calendar/registry.py +102 -0
- climate_toolkit/data/__init__.py +1 -0
- climate_toolkit/data/ggcmi_phase3/__init__.py +1 -0
- climate_toolkit/data/ggcmi_phase3/crop_calendar.parquet +0 -0
- climate_toolkit/data/ggcmi_phase3/crop_calendar_manifest.json +42 -0
- climate_toolkit/fetch_data/__init__.py +61 -0
- climate_toolkit/fetch_data/cache_inventory.py +378 -0
- climate_toolkit/fetch_data/fetch_data.py +645 -0
- climate_toolkit/fetch_data/gee_xee_batch.py +1133 -0
- climate_toolkit/fetch_data/multi_site.py +220 -0
- climate_toolkit/fetch_data/nex_gddp_batch.py +1017 -0
- climate_toolkit/fetch_data/preprocess_data/__init__.py +18 -0
- climate_toolkit/fetch_data/preprocess_data/preprocess_data.py +332 -0
- climate_toolkit/fetch_data/runtime_notes.py +80 -0
- climate_toolkit/fetch_data/source_data/__init__.py +15 -0
- climate_toolkit/fetch_data/source_data/source_data.py +398 -0
- climate_toolkit/fetch_data/source_data/sources/agera_5.py +15 -0
- climate_toolkit/fetch_data/source_data/sources/chirps.py +63 -0
- climate_toolkit/fetch_data/source_data/sources/chirts.py +63 -0
- climate_toolkit/fetch_data/source_data/sources/era_5.py +15 -0
- climate_toolkit/fetch_data/source_data/sources/gee.py +999 -0
- climate_toolkit/fetch_data/source_data/sources/gee_xee.py +107 -0
- climate_toolkit/fetch_data/source_data/sources/ghcn_daily.py +87 -0
- climate_toolkit/fetch_data/source_data/sources/gsod.py +87 -0
- climate_toolkit/fetch_data/source_data/sources/imerg.py +106 -0
- climate_toolkit/fetch_data/source_data/sources/nasa_power.py +414 -0
- climate_toolkit/fetch_data/source_data/sources/nex_gddp.py +357 -0
- climate_toolkit/fetch_data/source_data/sources/nex_gddp_xee.py +1062 -0
- climate_toolkit/fetch_data/source_data/sources/soil_grid.py +58 -0
- climate_toolkit/fetch_data/source_data/sources/tamsat.py +647 -0
- climate_toolkit/fetch_data/source_data/sources/terraclimate.py +96 -0
- climate_toolkit/fetch_data/source_data/sources/utils/__init__.py +177 -0
- climate_toolkit/fetch_data/source_data/sources/utils/config.yaml +227 -0
- climate_toolkit/fetch_data/source_data/sources/utils/models.py +539 -0
- climate_toolkit/fetch_data/source_data/sources/utils/settings.py +206 -0
- climate_toolkit/fetch_data/source_data/sources/xee_common.py +221 -0
- climate_toolkit/fetch_data/transform_data/__init__.py +20 -0
- climate_toolkit/fetch_data/transform_data/data_dictionary.yaml +96 -0
- climate_toolkit/fetch_data/transform_data/transform_data.py +343 -0
- climate_toolkit/gee_check.py +280 -0
- climate_toolkit/pipeline.py +307 -0
- climate_toolkit/season_analysis/__init__.py +24 -0
- climate_toolkit/season_analysis/ensemble.py +1016 -0
- climate_toolkit/season_analysis/season_identity.py +58 -0
- climate_toolkit/season_analysis/seasons.py +1817 -0
- climate_toolkit/weather_station/__init__.py +73 -0
- climate_toolkit/weather_station/compare.py +3236 -0
- climate_toolkit/weather_station/custom_station.py +464 -0
- climate_toolkit/weather_station/dem.py +153 -0
- climate_toolkit/weather_station/download.py +1440 -0
- climate_toolkit/weather_station/ghcn_daily.py +832 -0
- climate_toolkit/weather_station/gsod.py +835 -0
- climate_toolkit/weather_station/overrides.py +174 -0
- climate_toolkit/weather_station/station_selector.py +607 -0
- climate_toolkit-0.1.0.dist-info/METADATA +1548 -0
- climate_toolkit-0.1.0.dist-info/RECORD +85 -0
- climate_toolkit-0.1.0.dist-info/WHEEL +5 -0
- climate_toolkit-0.1.0.dist-info/entry_points.txt +18 -0
- climate_toolkit-0.1.0.dist-info/licenses/LICENSE +21 -0
- climate_toolkit-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Location-based climate analysis toolkit for agriculture.
|
|
2
|
+
|
|
3
|
+
Fetch daily climate data, compute seasonal climatologies and drought
|
|
4
|
+
indices, assess crop and livestock hazards, and compare periods, data
|
|
5
|
+
sources, and weather stations — for any point location.
|
|
6
|
+
|
|
7
|
+
Public functions
|
|
8
|
+
----------------
|
|
9
|
+
fetch_climate_data(source, location_coord, ...)
|
|
10
|
+
Download daily climate data for a site as a pandas DataFrame.
|
|
11
|
+
analyze_climate_statistics(location_coord, start_year, end_year, source, ...)
|
|
12
|
+
Seasonal climatology, water balance, and indices (SPI/SPEI) over a
|
|
13
|
+
multi-year window.
|
|
14
|
+
evaluate_hazards(crop_name, location_coord, date_from, date_to, ...)
|
|
15
|
+
Crop/livestock hazard assessment (heat, drought, waterlogging, ...)
|
|
16
|
+
for a growing season.
|
|
17
|
+
compare_climate_periods(location, baseline_start, baseline_end, focal_year, ...)
|
|
18
|
+
Diff a focal year against a baseline climatology.
|
|
19
|
+
compare_climate_sources(sources, lat, lon, start, end, ...)
|
|
20
|
+
Side-by-side comparison of gridded datasets for one site.
|
|
21
|
+
download_station_data(station_source, station_coord, date_from, date_to, ...)
|
|
22
|
+
Fetch daily observations from nearby weather stations.
|
|
23
|
+
compare_station_to_grids(station_source, station_coord, ..., grid_sources)
|
|
24
|
+
Validate gridded datasets against station observations.
|
|
25
|
+
|
|
26
|
+
Getting started
|
|
27
|
+
---------------
|
|
28
|
+
>>> import climate_toolkit as ct
|
|
29
|
+
>>> from datetime import date
|
|
30
|
+
>>> df = ct.fetch_climate_data(
|
|
31
|
+
... source="nasa_power", # needs no credentials
|
|
32
|
+
... location_coord=(-1.286, 36.817), # Nairobi
|
|
33
|
+
... date_from=date(2020, 1, 1),
|
|
34
|
+
... date_to=date(2020, 12, 31),
|
|
35
|
+
... )
|
|
36
|
+
|
|
37
|
+
Use ``help(ct.fetch_climate_data)`` (or any function above) for full
|
|
38
|
+
parameter documentation.
|
|
39
|
+
|
|
40
|
+
Data sources
|
|
41
|
+
------------
|
|
42
|
+
``nasa_power`` works with no setup. Earth Engine-backed sources
|
|
43
|
+
(``agera_5``, ``era_5``, ``chirps_v3_daily_rnl``, ``nex_gddp``) require
|
|
44
|
+
``earthengine authenticate`` and a ``GCP_PROJECT_ID`` environment
|
|
45
|
+
variable (free for noncommercial use). See ``examples/basic_usage.py``
|
|
46
|
+
in the repository for a full walkthrough.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"__version__",
|
|
55
|
+
"analyze_climate_statistics",
|
|
56
|
+
"compare_climate_periods",
|
|
57
|
+
"compare_climate_sources",
|
|
58
|
+
"compare_station_to_grids",
|
|
59
|
+
"download_station_data",
|
|
60
|
+
"evaluate_hazards",
|
|
61
|
+
"fetch_climate_data",
|
|
62
|
+
"run_pipeline",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
__version__ = version("climate-toolkit")
|
|
68
|
+
except PackageNotFoundError: # pragma: no cover - local source tree before install
|
|
69
|
+
__version__ = "0.0.0"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def __getattr__(name: str):
|
|
73
|
+
if name == "fetch_climate_data":
|
|
74
|
+
from .fetch_data.fetch_data import fetch_data as _fetch_data
|
|
75
|
+
|
|
76
|
+
return _fetch_data
|
|
77
|
+
if name == "run_pipeline":
|
|
78
|
+
from .pipeline import run_pipeline as _run_pipeline
|
|
79
|
+
|
|
80
|
+
return _run_pipeline
|
|
81
|
+
if name == "analyze_climate_statistics":
|
|
82
|
+
from .climate_statistics.statistics import (
|
|
83
|
+
analyze_climate_statistics as _analyze_climate_statistics,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return _analyze_climate_statistics
|
|
87
|
+
if name == "compare_climate_periods":
|
|
88
|
+
from .compare_periods.periods import compare as _compare_periods
|
|
89
|
+
|
|
90
|
+
return _compare_periods
|
|
91
|
+
if name == "compare_climate_sources":
|
|
92
|
+
from .compare_datasets.compare_datasets import compare_sources as _compare_sources
|
|
93
|
+
|
|
94
|
+
return _compare_sources
|
|
95
|
+
if name == "evaluate_hazards":
|
|
96
|
+
from .calculate_hazards.hazards import calculate_hazards as _calculate_hazards
|
|
97
|
+
|
|
98
|
+
return _calculate_hazards
|
|
99
|
+
if name == "download_station_data":
|
|
100
|
+
from .weather_station.download import download_station_data as _download_station_data
|
|
101
|
+
|
|
102
|
+
return _download_station_data
|
|
103
|
+
if name == "compare_station_to_grids":
|
|
104
|
+
from .weather_station.compare import (
|
|
105
|
+
compare_station_to_grids as _compare_station_to_grids,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return _compare_station_to_grids
|
|
109
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Helpers for loading packaged toolkit resources."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from importlib.resources import as_file, files
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Iterator
|
|
10
|
+
|
|
11
|
+
import yaml
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def package_resource_exists(package: str, resource_name: str) -> bool:
|
|
15
|
+
"""Return True when a packaged resource is available."""
|
|
16
|
+
return files(package).joinpath(resource_name).is_file()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _require_package_resource(package: str, resource_name: str) -> Any:
|
|
20
|
+
resource = files(package).joinpath(resource_name)
|
|
21
|
+
if not resource.is_file():
|
|
22
|
+
raise FileNotFoundError(f"Missing packaged resource {package}:{resource_name}")
|
|
23
|
+
return resource
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@contextmanager
|
|
27
|
+
def packaged_resource_path(package: str, resource_name: str) -> Iterator[Path]:
|
|
28
|
+
"""Yield a real filesystem path for a packaged resource."""
|
|
29
|
+
resource = _require_package_resource(package, resource_name)
|
|
30
|
+
with as_file(resource) as path:
|
|
31
|
+
yield path
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def load_json_resource(package: str, resource_name: str) -> Any:
|
|
35
|
+
"""Load a packaged JSON resource."""
|
|
36
|
+
resource = _require_package_resource(package, resource_name)
|
|
37
|
+
with resource.open("r", encoding="utf-8") as handle:
|
|
38
|
+
return json.load(handle)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def load_yaml_resource(package: str, resource_name: str) -> Any:
|
|
42
|
+
"""Load a packaged YAML resource."""
|
|
43
|
+
resource = _require_package_resource(package, resource_name)
|
|
44
|
+
with resource.open("r", encoding="utf-8") as handle:
|
|
45
|
+
return yaml.safe_load(handle)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Hazard analysis public subpackage API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib import import_module
|
|
6
|
+
|
|
7
|
+
__all__ = ["calculate_hazards"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def __getattr__(name: str):
|
|
11
|
+
if name == "calculate_hazards":
|
|
12
|
+
module = import_module(".hazards", __name__)
|
|
13
|
+
return getattr(module, name)
|
|
14
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Beans": {
|
|
3
|
+
"kc_init": 0.5,
|
|
4
|
+
"kc_mid": 1.15,
|
|
5
|
+
"kc_end": 0.35,
|
|
6
|
+
"root_depth_m": 0.6,
|
|
7
|
+
"depletion_fraction_p": 0.45,
|
|
8
|
+
"source_doc": "FAO-56 starter default"
|
|
9
|
+
},
|
|
10
|
+
"Maize": {
|
|
11
|
+
"kc_init": 0.3,
|
|
12
|
+
"kc_mid": 1.2,
|
|
13
|
+
"kc_end": 0.6,
|
|
14
|
+
"root_depth_m": 1.5,
|
|
15
|
+
"depletion_fraction_p": 0.55,
|
|
16
|
+
"source_doc": "FAO-56 starter default"
|
|
17
|
+
},
|
|
18
|
+
"Millet": {
|
|
19
|
+
"kc_init": 0.3,
|
|
20
|
+
"kc_mid": 1.0,
|
|
21
|
+
"kc_end": 0.45,
|
|
22
|
+
"root_depth_m": 1.2,
|
|
23
|
+
"depletion_fraction_p": 0.55,
|
|
24
|
+
"source_doc": "FAO-56 starter default"
|
|
25
|
+
},
|
|
26
|
+
"Groundnuts": {
|
|
27
|
+
"kc_init": 0.4,
|
|
28
|
+
"kc_mid": 1.15,
|
|
29
|
+
"kc_end": 0.6,
|
|
30
|
+
"root_depth_m": 0.7,
|
|
31
|
+
"depletion_fraction_p": 0.5,
|
|
32
|
+
"source_doc": "FAO-56 starter default"
|
|
33
|
+
},
|
|
34
|
+
"Sorghum": {
|
|
35
|
+
"kc_init": 0.35,
|
|
36
|
+
"kc_mid": 1.05,
|
|
37
|
+
"kc_end": 0.55,
|
|
38
|
+
"root_depth_m": 1.5,
|
|
39
|
+
"depletion_fraction_p": 0.55,
|
|
40
|
+
"source_doc": "FAO-56 starter default"
|
|
41
|
+
},
|
|
42
|
+
"Cassava": {
|
|
43
|
+
"kc_init": 0.45,
|
|
44
|
+
"kc_mid": 1.1,
|
|
45
|
+
"kc_end": 0.8,
|
|
46
|
+
"root_depth_m": 1.2,
|
|
47
|
+
"depletion_fraction_p": 0.5,
|
|
48
|
+
"source_doc": "FAO-56 starter default"
|
|
49
|
+
},
|
|
50
|
+
"Rice": {
|
|
51
|
+
"kc_init": 1.05,
|
|
52
|
+
"kc_mid": 1.2,
|
|
53
|
+
"kc_end": 0.9,
|
|
54
|
+
"root_depth_m": 0.5,
|
|
55
|
+
"depletion_fraction_p": 0.2,
|
|
56
|
+
"source_doc": "FAO-56 starter default"
|
|
57
|
+
}
|
|
58
|
+
}
|