hydrosovereign 6.5.0__tar.gz

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 (32) hide show
  1. hydrosovereign-6.5.0/LICENSE +19 -0
  2. hydrosovereign-6.5.0/PKG-INFO +140 -0
  3. hydrosovereign-6.5.0/README.md +100 -0
  4. hydrosovereign-6.5.0/hydrosovereign/__init__.py +41 -0
  5. hydrosovereign-6.5.0/hydrosovereign/__main__.py +6 -0
  6. hydrosovereign-6.5.0/hydrosovereign/alerts.py +61 -0
  7. hydrosovereign-6.5.0/hydrosovereign/api.py +170 -0
  8. hydrosovereign-6.5.0/hydrosovereign/api_server.py +293 -0
  9. hydrosovereign-6.5.0/hydrosovereign/async_alerts.py +142 -0
  10. hydrosovereign-6.5.0/hydrosovereign/basins.py +113 -0
  11. hydrosovereign-6.5.0/hydrosovereign/cli.py +126 -0
  12. hydrosovereign-6.5.0/hydrosovereign/data/__init__.py +20 -0
  13. hydrosovereign-6.5.0/hydrosovereign/data/fetchers.py +647 -0
  14. hydrosovereign-6.5.0/hydrosovereign/data/nile_basin_sample.json +12801 -0
  15. hydrosovereign-6.5.0/hydrosovereign/hbv.py +344 -0
  16. hydrosovereign-6.5.0/hydrosovereign/indices.py +154 -0
  17. hydrosovereign-6.5.0/hydrosovereign/legal.py +94 -0
  18. hydrosovereign-6.5.0/hydrosovereign/models/__init__.py +11 -0
  19. hydrosovereign-6.5.0/hydrosovereign/models/hbv.py +193 -0
  20. hydrosovereign-6.5.0/hydrosovereign/viz/__init__.py +35 -0
  21. hydrosovereign-6.5.0/hydrosovereign/viz/maps.py +240 -0
  22. hydrosovereign-6.5.0/hydrosovereign/viz/plots.py +401 -0
  23. hydrosovereign-6.5.0/hydrosovereign.egg-info/PKG-INFO +140 -0
  24. hydrosovereign-6.5.0/hydrosovereign.egg-info/SOURCES.txt +30 -0
  25. hydrosovereign-6.5.0/hydrosovereign.egg-info/dependency_links.txt +1 -0
  26. hydrosovereign-6.5.0/hydrosovereign.egg-info/entry_points.txt +3 -0
  27. hydrosovereign-6.5.0/hydrosovereign.egg-info/requires.txt +22 -0
  28. hydrosovereign-6.5.0/hydrosovereign.egg-info/top_level.txt +1 -0
  29. hydrosovereign-6.5.0/pyproject.toml +54 -0
  30. hydrosovereign-6.5.0/setup.cfg +4 -0
  31. hydrosovereign-6.5.0/tests/test_core.py +189 -0
  32. hydrosovereign-6.5.0/tests/test_package.py +312 -0
@@ -0,0 +1,19 @@
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2026 Seifeldin M.G. Alkedir
5
+ ORCID: 0000-0003-0821-2991
6
+ University of Khartoum
7
+
8
+ This program is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: hydrosovereign
3
+ Version: 6.5.0
4
+ Summary: HydroSovereign AI Engine — Python package for hydrological analysis, satellite data, and water sovereignty assessment
5
+ Author-email: "Seifeldin M.G. Alkedir" <saifeldinkhedir@gmail.com>
6
+ License: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/saifeldinkhedir-coder/hydrosovereign
8
+ Project-URL: DOI, https://doi.org/10.5281/zenodo.19180160
9
+ Keywords: hydrology,GEE,satellite,water,HSAE,reservoir
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Hydrology
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: numpy>=1.24
23
+ Requires-Dist: pandas>=2.0
24
+ Requires-Dist: scipy>=1.10
25
+ Requires-Dist: requests>=2.31
26
+ Provides-Extra: gee
27
+ Requires-Dist: earthengine-api>=0.1.400; extra == "gee"
28
+ Provides-Extra: viz
29
+ Requires-Dist: plotly>=5.18; extra == "viz"
30
+ Requires-Dist: folium>=0.16; extra == "viz"
31
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
32
+ Provides-Extra: server
33
+ Requires-Dist: fastapi>=0.110; extra == "server"
34
+ Requires-Dist: uvicorn>=0.27; extra == "server"
35
+ Provides-Extra: alerts
36
+ Requires-Dist: python-telegram-bot>=20.0; extra == "alerts"
37
+ Provides-Extra: all
38
+ Requires-Dist: hydrosovereign[alerts,gee,server,viz]; extra == "all"
39
+ Dynamic: license-file
40
+
41
+ # HydroSovereign AI Engine (HSAE)
42
+
43
+ [![PyPI version](https://badge.fury.io/py/hydrosovereign.svg)](https://pypi.org/project/hydrosovereign/)
44
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.19180160.svg)](https://doi.org/10.5281/zenodo.19180160)
45
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
46
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
47
+
48
+ **Author:** Seifeldin M.G. Alkedir · ORCID: [0000-0003-0821-2991](https://orcid.org/0000-0003-0821-2991)
49
+ **Affiliation:** University of Khartoum
50
+ **DOI:** [10.5281/zenodo.19180160](https://doi.org/10.5281/zenodo.19180160)
51
+
52
+ ---
53
+
54
+ ## Overview
55
+
56
+ HydroSovereign AI Engine (HSAE) v6.5.0 is a Python package for:
57
+
58
+ - **Hydrological basin analysis** — water balance, inflow, outflow, storage
59
+ - **Real satellite data ingestion** — GPM IMERG, GRACE-FO, Sentinel-1/2, SMAP, GloFAS, ERA5
60
+ - **Water sovereignty assessment** — Alkedir Transparency Deficit Index (ATDI)
61
+ - **Forensic hydrology** — closure error, mass balance analysis
62
+ - **HBV rainfall-runoff modelling** — calibration and simulation
63
+ - **AI ensemble forecasting** — Random Forest, ensemble methods
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ pip install hydrosovereign
69
+ ```
70
+
71
+ With optional dependencies:
72
+ ```bash
73
+ pip install hydrosovereign[gee] # Google Earth Engine support
74
+ pip install hydrosovereign[viz] # Plotly + Folium visualizations
75
+ pip install hydrosovereign[all] # All dependencies
76
+ ```
77
+
78
+ ## Quick Start
79
+
80
+ ```python
81
+ import hydrosovereign as hsae
82
+
83
+ # Analyze a basin
84
+ result = hsae.analyze_basin(
85
+ basin_id = "GERD_ETH",
86
+ start_date = "2024-01-01",
87
+ end_date = "2024-12-31",
88
+ )
89
+
90
+ print(result["nse"]) # Nash-Sutcliffe Efficiency
91
+ print(result["atdi"]) # Alkedir Transparency Deficit Index
92
+ print(result["volume"]) # Reservoir volume (BCM)
93
+ ```
94
+
95
+ ```python
96
+ # Fetch real satellite data
97
+ from hydrosovereign.data import fetch_basin_forcing
98
+
99
+ forcing = fetch_basin_forcing("GERD_ETH", "2024-01-01", "2024-12-31")
100
+ print(forcing["gpm"]["mean_P"]) # GPM precipitation mm/day
101
+ print(forcing["grace"]["tws_cm"]) # GRACE-FO TWS anomaly
102
+ ```
103
+
104
+ ```python
105
+ # HBV rainfall-runoff model
106
+ from hydrosovereign.models import HBVModel
107
+
108
+ model = HBVModel()
109
+ model.fit(P=forcing["P"], T=forcing["T"], Q_obs=forcing["Q"])
110
+ print(f"NSE = {model.nse:.3f}")
111
+ ```
112
+
113
+ ## CLI
114
+
115
+ ```bash
116
+ hydrosovereign analyze --basin GERD_ETH --year 2024
117
+ hydrosovereign fetch-gee --basin KAINJI_NGA --start 2023-01-01 --end 2023-12-31
118
+ ```
119
+
120
+ ## Live Application
121
+
122
+ The full HSAE v6.01 Streamlit application:
123
+ 🌐 [https://hydrosovereign-ai-engine-hsae-v601-6euz2zxcmerkzxgordmvxf.streamlit.app](https://hydrosovereign-ai-engine-hsae-v601-6euz2zxcmerkzxgordmvxf.streamlit.app)
124
+
125
+ ## Citation
126
+
127
+ ```bibtex
128
+ @software{alkedir2026hsae,
129
+ author = {Alkedir, Seifeldin M.G.},
130
+ title = {HydroSovereign AI Engine (HSAE) v6.5.0},
131
+ year = {2026},
132
+ doi = {10.5281/zenodo.19180160},
133
+ url = {https://github.com/saifeldinkhedir-coder/hydrosovereign},
134
+ orcid = {0000-0003-0821-2991},
135
+ }
136
+ ```
137
+
138
+ ## License
139
+
140
+ GNU General Public License v3.0 — see [LICENSE](LICENSE)
@@ -0,0 +1,100 @@
1
+ # HydroSovereign AI Engine (HSAE)
2
+
3
+ [![PyPI version](https://badge.fury.io/py/hydrosovereign.svg)](https://pypi.org/project/hydrosovereign/)
4
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.19180160.svg)](https://doi.org/10.5281/zenodo.19180160)
5
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
6
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
7
+
8
+ **Author:** Seifeldin M.G. Alkedir · ORCID: [0000-0003-0821-2991](https://orcid.org/0000-0003-0821-2991)
9
+ **Affiliation:** University of Khartoum
10
+ **DOI:** [10.5281/zenodo.19180160](https://doi.org/10.5281/zenodo.19180160)
11
+
12
+ ---
13
+
14
+ ## Overview
15
+
16
+ HydroSovereign AI Engine (HSAE) v6.5.0 is a Python package for:
17
+
18
+ - **Hydrological basin analysis** — water balance, inflow, outflow, storage
19
+ - **Real satellite data ingestion** — GPM IMERG, GRACE-FO, Sentinel-1/2, SMAP, GloFAS, ERA5
20
+ - **Water sovereignty assessment** — Alkedir Transparency Deficit Index (ATDI)
21
+ - **Forensic hydrology** — closure error, mass balance analysis
22
+ - **HBV rainfall-runoff modelling** — calibration and simulation
23
+ - **AI ensemble forecasting** — Random Forest, ensemble methods
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install hydrosovereign
29
+ ```
30
+
31
+ With optional dependencies:
32
+ ```bash
33
+ pip install hydrosovereign[gee] # Google Earth Engine support
34
+ pip install hydrosovereign[viz] # Plotly + Folium visualizations
35
+ pip install hydrosovereign[all] # All dependencies
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```python
41
+ import hydrosovereign as hsae
42
+
43
+ # Analyze a basin
44
+ result = hsae.analyze_basin(
45
+ basin_id = "GERD_ETH",
46
+ start_date = "2024-01-01",
47
+ end_date = "2024-12-31",
48
+ )
49
+
50
+ print(result["nse"]) # Nash-Sutcliffe Efficiency
51
+ print(result["atdi"]) # Alkedir Transparency Deficit Index
52
+ print(result["volume"]) # Reservoir volume (BCM)
53
+ ```
54
+
55
+ ```python
56
+ # Fetch real satellite data
57
+ from hydrosovereign.data import fetch_basin_forcing
58
+
59
+ forcing = fetch_basin_forcing("GERD_ETH", "2024-01-01", "2024-12-31")
60
+ print(forcing["gpm"]["mean_P"]) # GPM precipitation mm/day
61
+ print(forcing["grace"]["tws_cm"]) # GRACE-FO TWS anomaly
62
+ ```
63
+
64
+ ```python
65
+ # HBV rainfall-runoff model
66
+ from hydrosovereign.models import HBVModel
67
+
68
+ model = HBVModel()
69
+ model.fit(P=forcing["P"], T=forcing["T"], Q_obs=forcing["Q"])
70
+ print(f"NSE = {model.nse:.3f}")
71
+ ```
72
+
73
+ ## CLI
74
+
75
+ ```bash
76
+ hydrosovereign analyze --basin GERD_ETH --year 2024
77
+ hydrosovereign fetch-gee --basin KAINJI_NGA --start 2023-01-01 --end 2023-12-31
78
+ ```
79
+
80
+ ## Live Application
81
+
82
+ The full HSAE v6.01 Streamlit application:
83
+ 🌐 [https://hydrosovereign-ai-engine-hsae-v601-6euz2zxcmerkzxgordmvxf.streamlit.app](https://hydrosovereign-ai-engine-hsae-v601-6euz2zxcmerkzxgordmvxf.streamlit.app)
84
+
85
+ ## Citation
86
+
87
+ ```bibtex
88
+ @software{alkedir2026hsae,
89
+ author = {Alkedir, Seifeldin M.G.},
90
+ title = {HydroSovereign AI Engine (HSAE) v6.5.0},
91
+ year = {2026},
92
+ doi = {10.5281/zenodo.19180160},
93
+ url = {https://github.com/saifeldinkhedir-coder/hydrosovereign},
94
+ orcid = {0000-0003-0821-2991},
95
+ }
96
+ ```
97
+
98
+ ## License
99
+
100
+ GNU General Public License v3.0 — see [LICENSE](LICENSE)
@@ -0,0 +1,41 @@
1
+ """
2
+ HydroSovereign AI Engine (HSAE) v6.5.0
3
+ ========================================
4
+ Author: Seifeldin M.G. Alkedir · ORCID: 0000-0003-0821-2991
5
+ DOI: 10.5281/zenodo.19180160
6
+ """
7
+
8
+ __version__ = "6.5.0"
9
+ __author__ = "Seifeldin M.G. Alkedir"
10
+ __email__ = "saifeldinkhedir@gmail.com"
11
+ __orcid__ = "0000-0003-0821-2991"
12
+ __doi__ = "10.5281/zenodo.19180160"
13
+ __license__ = "GPL-3.0"
14
+ __app_url__ = "https://hydrosovereign-ai-engine-hsae-v601-6euz2zxcmerkzxgordmvxf.streamlit.app"
15
+
16
+ # Core API — always available
17
+ from .api import analyze_basin, analyze_all_basins
18
+
19
+ # Models — always available (pure Python + numpy)
20
+ from .models import HBVModel
21
+
22
+ # Indices — always available
23
+ from .indices import compute_atdi, compute_kge, compute_nse
24
+
25
+ # Optional imports — only if dependencies installed
26
+ try:
27
+ from .data import fetch_basin_forcing, fetch_openmeteo
28
+ except ImportError:
29
+ pass
30
+
31
+ try:
32
+ from .viz import plot_water_balance, plot_forcing
33
+ except ImportError:
34
+ pass
35
+
36
+ __all__ = [
37
+ "__version__", "__author__", "__orcid__", "__doi__",
38
+ "analyze_basin", "analyze_all_basins",
39
+ "HBVModel",
40
+ "compute_atdi", "compute_kge", "compute_nse",
41
+ ]
@@ -0,0 +1,6 @@
1
+ """
2
+ hydrosovereign.__main__ — enables: python3 -m hydrosovereign
3
+ """
4
+ from hydrosovereign.cli import main
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,61 @@
1
+ """
2
+ alerts.py — HSAE v6.01 Alert System
3
+ =====================================
4
+ 4-level alert system for ATDI/HIFD thresholds.
5
+
6
+ Author: Seifeldin M.G. Alkedir · ORCID: 0000-0003-0821-2991
7
+ """
8
+
9
+ from __future__ import annotations
10
+ from enum import Enum
11
+
12
+
13
+ class AlertLevel(Enum):
14
+ INFO = "INFO"
15
+ ALERT = "ALERT"
16
+ WARNING = "WARNING"
17
+ CRITICAL = "CRITICAL"
18
+
19
+
20
+ def check_atdi_alert(atdi: float) -> AlertLevel:
21
+ """
22
+ Return alert level based on ATDI.
23
+
24
+ Thresholds:
25
+ - CRITICAL : ATDI >= 70%
26
+ - WARNING : ATDI >= 55%
27
+ - ALERT : ATDI >= 40%
28
+ - INFO : ATDI < 40%
29
+ """
30
+ if atdi >= 70: return AlertLevel.CRITICAL
31
+ if atdi >= 55: return AlertLevel.WARNING
32
+ if atdi >= 40: return AlertLevel.ALERT
33
+ return AlertLevel.INFO
34
+
35
+
36
+ def check_hifd_alert(hifd: float) -> AlertLevel:
37
+ """
38
+ Return alert level based on HIFD.
39
+
40
+ Thresholds:
41
+ - CRITICAL : HIFD >= 60%
42
+ - WARNING : HIFD >= 40%
43
+ - ALERT : HIFD >= 25%
44
+ - INFO : HIFD < 25%
45
+ """
46
+ if hifd >= 60: return AlertLevel.CRITICAL
47
+ if hifd >= 40: return AlertLevel.WARNING
48
+ if hifd >= 25: return AlertLevel.ALERT
49
+ return AlertLevel.INFO
50
+
51
+
52
+ def format_alert_message(basin_name: str, atdi: float,
53
+ hifd: float, level: AlertLevel) -> str:
54
+ """Format alert message for Telegram or logging."""
55
+ emoji = {"CRITICAL":"🔴","WARNING":"🟠","ALERT":"🟡","INFO":"🟢"}[level.value]
56
+ return (
57
+ f"{emoji} HSAE Alert — {level.value}\n"
58
+ f"Basin: {basin_name}\n"
59
+ f"ATDI: {atdi:.1f}% | HIFD: {hifd:.1f}%\n"
60
+ f"UNWC Arts: {', '.join(['Art.5','Art.9'] + (['Art.7'] if atdi>=40 else []) + (['Art.20'] if hifd>=25 else []))}"
61
+ )
@@ -0,0 +1,170 @@
1
+ """
2
+ api.py — HSAE v6.2.0 Unified High-Level API
3
+ =============================================
4
+ Single-call basin analysis as recommended by ChatGPT review:
5
+ "Add a clear entry point: analyze_basin(data)"
6
+
7
+ Author: Seifeldin M.G. Alkedir · ORCID: 0000-0003-0821-2991
8
+ """
9
+ from __future__ import annotations
10
+ import logging
11
+ from typing import Optional, Dict
12
+
13
+ from .indices import compute_all_indices
14
+ from .legal import get_legal_assessment
15
+ from .alerts import check_atdi_alert, check_hifd_alert, AlertLevel
16
+ from .basins import BasinRegistry, BASINS_26
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ def analyze_basin(
22
+ name: Optional[str] = None,
23
+ runoff_c: Optional[float] = None,
24
+ cap_bcm: Optional[float] = None,
25
+ n_countries: Optional[int] = None,
26
+ dispute_level: Optional[int] = None,
27
+ area_km2: Optional[float] = None,
28
+ wqi_measurements: Optional[Dict] = None,
29
+ include_negotiation: bool = True,
30
+ include_legal: bool = True,
31
+ ) -> dict:
32
+ """
33
+ Full basin analysis in one call — HSAE unified entry point.
34
+
35
+ Provide either basin name (auto-loads parameters) or all parameters manually.
36
+
37
+ Parameters
38
+ ----------
39
+ name : str, optional
40
+ Basin name from registry (e.g. "Blue Nile (GERD)"). Auto-fills parameters.
41
+ runoff_c : float, optional
42
+ Runoff coefficient 0–1. Required if name not given.
43
+ cap_bcm : float, optional
44
+ Dam storage capacity BCM.
45
+ n_countries : int, optional
46
+ Number of riparian states.
47
+ dispute_level : int, optional
48
+ TFDD/ICOW dispute level 0–4.
49
+ area_km2 : float, optional
50
+ Catchment area km². Used for conflict sensitivity.
51
+ wqi_measurements : dict, optional
52
+ Physicochemical measurements for WQI (ph, do, bod, turbidity...).
53
+ include_negotiation : bool
54
+ Include Negotiation AI prediction. Default = True.
55
+ include_legal : bool
56
+ Include UNWC legal assessment. Default = True.
57
+
58
+ Returns
59
+ -------
60
+ dict
61
+ Complete basin analysis:
62
+ - indices : atdi, hifd, wqi, ci, nse, kge
63
+ - alerts : atdi_alert, hifd_alert
64
+ - legal : articles, recommendation, pathway
65
+ - ai : negotiation result
66
+ - metadata : basin name, parameters used
67
+
68
+ Examples
69
+ --------
70
+ >>> # From registry
71
+ >>> result = analyze_basin("Blue Nile (GERD)")
72
+ >>> print(result["indices"]["atdi"]) # ~53.5
73
+ >>> print(result["ai"]["p_success"]) # ~0.37
74
+ >>> print(result["alerts"]["atdi_alert"]) # ALERT
75
+
76
+ >>> # Manual parameters
77
+ >>> result = analyze_basin(runoff_c=0.38, cap_bcm=74, n_countries=3, dispute_level=4)
78
+ """
79
+ # Load from registry if name given
80
+ if name is not None:
81
+ reg = BasinRegistry()
82
+ basin = reg.get(name)
83
+ runoff_c = runoff_c or float(basin.get("runoff_c", 0.3))
84
+ cap_bcm = cap_bcm or float(basin.get("cap", basin.get("cap_bcm", 10)))
85
+ n_countries = n_countries or (len(basin["country"]) if isinstance(basin.get("country"),list) else int(basin.get("n_countries",2)))
86
+ dispute_level = dispute_level if dispute_level is not None else int(basin.get("dispute_level",0))
87
+ area_km2 = area_km2 or float(basin.get("eff_cat_km2", basin.get("area_km2",100000)))
88
+ else:
89
+ if any(v is None for v in [runoff_c, cap_bcm, n_countries, dispute_level]):
90
+ raise ValueError("Provide basin name or all of: runoff_c, cap_bcm, n_countries, dispute_level")
91
+ area_km2 = area_km2 or 100000.0
92
+
93
+ # Core indices
94
+ indices = compute_all_indices(runoff_c, cap_bcm, n_countries, dispute_level,
95
+ wqi_measurements=wqi_measurements)
96
+
97
+ # Alerts
98
+ atdi_alert = check_atdi_alert(indices["atdi"])
99
+ hifd_alert = check_hifd_alert(indices["hifd"])
100
+
101
+ result = {
102
+ "indices": indices,
103
+ "alerts": {
104
+ "atdi_alert": atdi_alert.value,
105
+ "hifd_alert": hifd_alert.value,
106
+ "overall": ("CRITICAL" if AlertLevel.CRITICAL in (atdi_alert,hifd_alert)
107
+ else "WARNING" if AlertLevel.WARNING in (atdi_alert,hifd_alert)
108
+ else "ALERT" if AlertLevel.ALERT in (atdi_alert,hifd_alert)
109
+ else "INFO"),
110
+ },
111
+ "legal": None,
112
+ "ai": None,
113
+ "metadata": {
114
+ "name": name or "custom",
115
+ "runoff_c": runoff_c,
116
+ "cap_bcm": cap_bcm,
117
+ "n_countries": n_countries,
118
+ "dispute_level": dispute_level,
119
+ "area_km2": area_km2,
120
+ "package_version": "6.2.0",
121
+ }
122
+ }
123
+
124
+ if include_legal:
125
+ result["legal"] = get_legal_assessment(
126
+ indices["atdi"], indices["hifd"], dispute_level, n_countries)
127
+
128
+ if include_negotiation:
129
+ from .ai.negotiation import NegotiationAI
130
+ ai = NegotiationAI()
131
+ result["ai"] = ai.predict(indices["atdi"], indices["hifd"],
132
+ n_countries, dispute_level)
133
+
134
+ logger.info("analyze_basin(%s): ATDI=%.1f HIFD=%.1f CI=%.3f alert=%s",
135
+ name or "custom", indices["atdi"], indices["hifd"],
136
+ indices["ci"], result["alerts"]["overall"])
137
+ return result
138
+
139
+
140
+ def analyze_all_basins(include_ai: bool = False) -> list:
141
+ """
142
+ Analyze all 26 registered transboundary basins.
143
+
144
+ Parameters
145
+ ----------
146
+ include_ai : bool
147
+ Include NegotiationAI for each basin (slower). Default = False.
148
+
149
+ Returns
150
+ -------
151
+ list of dict, sorted by conflict index descending.
152
+
153
+ Examples
154
+ --------
155
+ >>> results = analyze_all_basins()
156
+ >>> for r in results[:5]:
157
+ ... print(r["metadata"]["name"], r["indices"]["atdi"])
158
+ """
159
+ results = []
160
+ for basin in BASINS_26:
161
+ try:
162
+ r = analyze_basin(
163
+ name = basin["name"],
164
+ include_negotiation= include_ai,
165
+ include_legal = True,
166
+ )
167
+ results.append(r)
168
+ except Exception as e:
169
+ logger.warning("analyze_basin failed for %s: %s", basin.get("name","?"), e)
170
+ return sorted(results, key=lambda x: x["indices"]["ci"], reverse=True)