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.
Files changed (85) hide show
  1. climate_toolkit/__init__.py +109 -0
  2. climate_toolkit/_resources.py +45 -0
  3. climate_toolkit/calculate_hazards/__init__.py +14 -0
  4. climate_toolkit/calculate_hazards/crop_water_balance_params.json +58 -0
  5. climate_toolkit/calculate_hazards/ensemble_hazards.py +1317 -0
  6. climate_toolkit/calculate_hazards/hazards.py +3272 -0
  7. climate_toolkit/cli.py +89 -0
  8. climate_toolkit/climate_statistics/__init__.py +14 -0
  9. climate_toolkit/climate_statistics/ensemble_statistics.py +1065 -0
  10. climate_toolkit/climate_statistics/statistics.py +3375 -0
  11. climate_toolkit/climatology/__init__.py +104 -0
  12. climate_toolkit/climatology/_cli_common.py +172 -0
  13. climate_toolkit/climatology/heat_stress.py +675 -0
  14. climate_toolkit/climatology/human_heat_stress.py +389 -0
  15. climate_toolkit/climatology/long_term_climatology.py +1939 -0
  16. climate_toolkit/climatology/spei.py +745 -0
  17. climate_toolkit/climatology/vpd.py +246 -0
  18. climate_toolkit/climatology/xclim_reference.py +988 -0
  19. climate_toolkit/compare_datasets/__init__.py +14 -0
  20. climate_toolkit/compare_datasets/compare_datasets.py +1070 -0
  21. climate_toolkit/compare_periods/__init__.py +14 -0
  22. climate_toolkit/compare_periods/ensemble_periods.py +2899 -0
  23. climate_toolkit/compare_periods/periods.py +1892 -0
  24. climate_toolkit/crop_calendar/__init__.py +94 -0
  25. climate_toolkit/crop_calendar/ggcmi.py +198 -0
  26. climate_toolkit/crop_calendar/registry.py +102 -0
  27. climate_toolkit/data/__init__.py +1 -0
  28. climate_toolkit/data/ggcmi_phase3/__init__.py +1 -0
  29. climate_toolkit/data/ggcmi_phase3/crop_calendar.parquet +0 -0
  30. climate_toolkit/data/ggcmi_phase3/crop_calendar_manifest.json +42 -0
  31. climate_toolkit/fetch_data/__init__.py +61 -0
  32. climate_toolkit/fetch_data/cache_inventory.py +378 -0
  33. climate_toolkit/fetch_data/fetch_data.py +645 -0
  34. climate_toolkit/fetch_data/gee_xee_batch.py +1133 -0
  35. climate_toolkit/fetch_data/multi_site.py +220 -0
  36. climate_toolkit/fetch_data/nex_gddp_batch.py +1017 -0
  37. climate_toolkit/fetch_data/preprocess_data/__init__.py +18 -0
  38. climate_toolkit/fetch_data/preprocess_data/preprocess_data.py +332 -0
  39. climate_toolkit/fetch_data/runtime_notes.py +80 -0
  40. climate_toolkit/fetch_data/source_data/__init__.py +15 -0
  41. climate_toolkit/fetch_data/source_data/source_data.py +398 -0
  42. climate_toolkit/fetch_data/source_data/sources/agera_5.py +15 -0
  43. climate_toolkit/fetch_data/source_data/sources/chirps.py +63 -0
  44. climate_toolkit/fetch_data/source_data/sources/chirts.py +63 -0
  45. climate_toolkit/fetch_data/source_data/sources/era_5.py +15 -0
  46. climate_toolkit/fetch_data/source_data/sources/gee.py +999 -0
  47. climate_toolkit/fetch_data/source_data/sources/gee_xee.py +107 -0
  48. climate_toolkit/fetch_data/source_data/sources/ghcn_daily.py +87 -0
  49. climate_toolkit/fetch_data/source_data/sources/gsod.py +87 -0
  50. climate_toolkit/fetch_data/source_data/sources/imerg.py +106 -0
  51. climate_toolkit/fetch_data/source_data/sources/nasa_power.py +414 -0
  52. climate_toolkit/fetch_data/source_data/sources/nex_gddp.py +357 -0
  53. climate_toolkit/fetch_data/source_data/sources/nex_gddp_xee.py +1062 -0
  54. climate_toolkit/fetch_data/source_data/sources/soil_grid.py +58 -0
  55. climate_toolkit/fetch_data/source_data/sources/tamsat.py +647 -0
  56. climate_toolkit/fetch_data/source_data/sources/terraclimate.py +96 -0
  57. climate_toolkit/fetch_data/source_data/sources/utils/__init__.py +177 -0
  58. climate_toolkit/fetch_data/source_data/sources/utils/config.yaml +227 -0
  59. climate_toolkit/fetch_data/source_data/sources/utils/models.py +539 -0
  60. climate_toolkit/fetch_data/source_data/sources/utils/settings.py +206 -0
  61. climate_toolkit/fetch_data/source_data/sources/xee_common.py +221 -0
  62. climate_toolkit/fetch_data/transform_data/__init__.py +20 -0
  63. climate_toolkit/fetch_data/transform_data/data_dictionary.yaml +96 -0
  64. climate_toolkit/fetch_data/transform_data/transform_data.py +343 -0
  65. climate_toolkit/gee_check.py +280 -0
  66. climate_toolkit/pipeline.py +307 -0
  67. climate_toolkit/season_analysis/__init__.py +24 -0
  68. climate_toolkit/season_analysis/ensemble.py +1016 -0
  69. climate_toolkit/season_analysis/season_identity.py +58 -0
  70. climate_toolkit/season_analysis/seasons.py +1817 -0
  71. climate_toolkit/weather_station/__init__.py +73 -0
  72. climate_toolkit/weather_station/compare.py +3236 -0
  73. climate_toolkit/weather_station/custom_station.py +464 -0
  74. climate_toolkit/weather_station/dem.py +153 -0
  75. climate_toolkit/weather_station/download.py +1440 -0
  76. climate_toolkit/weather_station/ghcn_daily.py +832 -0
  77. climate_toolkit/weather_station/gsod.py +835 -0
  78. climate_toolkit/weather_station/overrides.py +174 -0
  79. climate_toolkit/weather_station/station_selector.py +607 -0
  80. climate_toolkit-0.1.0.dist-info/METADATA +1548 -0
  81. climate_toolkit-0.1.0.dist-info/RECORD +85 -0
  82. climate_toolkit-0.1.0.dist-info/WHEEL +5 -0
  83. climate_toolkit-0.1.0.dist-info/entry_points.txt +18 -0
  84. climate_toolkit-0.1.0.dist-info/licenses/LICENSE +21 -0
  85. 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
+ }