hestia-earth-models 0.59.4__py3-none-any.whl → 0.59.5__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.
Potentially problematic release.
This version of hestia-earth-models might be problematic. Click here for more details.
- hestia_earth/models/cycle/liveAnimal.py +3 -0
- hestia_earth/models/cycle/milkYield.py +1 -1
- hestia_earth/models/cycle/utils.py +1 -1
- hestia_earth/models/geospatialDatabase/potentialEvapotranspirationLongTermAnnualMean.py +2 -2
- hestia_earth/models/geospatialDatabase/potentialEvapotranspirationMonthly.py +9 -8
- hestia_earth/models/geospatialDatabase/precipitationMonthly.py +10 -8
- hestia_earth/models/geospatialDatabase/temperatureAnnual.py +2 -5
- hestia_earth/models/geospatialDatabase/temperatureLongTermAnnualMean.py +2 -3
- hestia_earth/models/geospatialDatabase/temperatureMonthly.py +8 -8
- hestia_earth/models/geospatialDatabase/utils.py +6 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +70 -110
- hestia_earth/models/linkedImpactAssessment/__init__.py +78 -43
- hestia_earth/models/mocking/search-results.json +0 -39
- hestia_earth/models/schmidt2007/n2OToAirWasteTreatmentDirect.py +58 -0
- hestia_earth/models/schmidt2007/nh3ToAirWasteTreatment.py +58 -0
- hestia_earth/models/site/management.py +104 -11
- hestia_earth/models/site/soilMeasurement.py +9 -9
- hestia_earth/models/utils/blank_node.py +3 -3
- hestia_earth/models/utils/term.py +0 -23
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.5.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.5.dist-info}/RECORD +31 -27
- tests/models/ipcc2019/test_organicCarbonPerHa.py +4 -18
- tests/models/schmidt2007/test_n2OToAirWasteTreatmentDirect.py +45 -0
- tests/models/schmidt2007/test_nh3ToAirWasteTreatment.py +45 -0
- tests/models/site/test_management.py +24 -3
- tests/models/site/test_soilMeasurement.py +40 -21
- tests/models/utils/test_term.py +1 -8
- {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.5.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.5.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.5.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ from . import MODEL
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def _get_liveAnimal_term_id(product: dict, **log_ars):
|
|
9
|
-
term_id = get_lookup_value(product.get('term', {}), '
|
|
9
|
+
term_id = get_lookup_value(product.get('term', {}), 'liveAnimalTermId', model=MODEL, **log_ars)
|
|
10
10
|
return term_id.split(';')[0] if term_id else None
|
|
11
11
|
|
|
12
12
|
|
|
@@ -47,9 +47,9 @@ def _measurement(value: float):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _download(site: dict):
|
|
50
|
-
|
|
50
|
+
factor = 0.1
|
|
51
51
|
value = download(TERM_ID, site, EE_PARAMS)
|
|
52
|
-
return value
|
|
52
|
+
return value * factor if value else None
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def _run(site: dict):
|
|
@@ -10,7 +10,7 @@ from hestia_earth.models.utils import first_day_of_month, last_day_of_month
|
|
|
10
10
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
11
11
|
from hestia_earth.models.utils.source import get_source
|
|
12
12
|
from hestia_earth.models.utils.site import related_years
|
|
13
|
-
from .utils import
|
|
13
|
+
from .utils import download, has_geospatial_data, should_download
|
|
14
14
|
from . import MODEL
|
|
15
15
|
|
|
16
16
|
REQUIREMENTS = {
|
|
@@ -48,9 +48,6 @@ def _measurement(site: dict, value: list, dates: list):
|
|
|
48
48
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def _to_celcius(kelvin_value: int): return kelvin_value - KELVIN_0 if kelvin_value else None
|
|
52
|
-
|
|
53
|
-
|
|
54
51
|
def _download(site: dict, start_date: str, end_date: str):
|
|
55
52
|
return download(
|
|
56
53
|
TERM_ID,
|
|
@@ -63,6 +60,12 @@ def _download(site: dict, start_date: str, end_date: str):
|
|
|
63
60
|
)
|
|
64
61
|
|
|
65
62
|
|
|
63
|
+
def _value_at(site: dict, start_date: str, end_date: str):
|
|
64
|
+
factor = 0.1
|
|
65
|
+
value = _download(site, start_date, end_date)
|
|
66
|
+
return (value * factor, start_date[0:7]) if value is not None else None
|
|
67
|
+
|
|
68
|
+
|
|
66
69
|
def _run(site: dict, years: list):
|
|
67
70
|
# fetch from first year to last
|
|
68
71
|
years = range(years[0], years[-1] + 1) if len(years) > 1 else years
|
|
@@ -73,10 +76,8 @@ def _run(site: dict, years: list):
|
|
|
73
76
|
for month in range(1, 13)
|
|
74
77
|
] for year in years
|
|
75
78
|
])
|
|
76
|
-
values = non_empty_list([
|
|
77
|
-
|
|
78
|
-
])
|
|
79
|
-
return _measurement(site, [v for v, d in values], [d for v, d in values])
|
|
79
|
+
values = non_empty_list([_value_at(site, start_date, end_date) for start_date, end_date in dates])
|
|
80
|
+
return [_measurement(site, [v for v, d in values], [d for v, d in values])] if values else []
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
def run(site: dict):
|
|
@@ -10,7 +10,7 @@ from hestia_earth.models.utils import first_day_of_month, last_day_of_month
|
|
|
10
10
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
11
11
|
from hestia_earth.models.utils.source import get_source
|
|
12
12
|
from hestia_earth.models.utils.site import related_years
|
|
13
|
-
from .utils import
|
|
13
|
+
from .utils import download, has_geospatial_data, should_download
|
|
14
14
|
from . import MODEL
|
|
15
15
|
|
|
16
16
|
REQUIREMENTS = {
|
|
@@ -48,9 +48,6 @@ def _measurement(site: dict, value: list, dates: list):
|
|
|
48
48
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def _to_celcius(kelvin_value: int): return kelvin_value - KELVIN_0 if kelvin_value else None
|
|
52
|
-
|
|
53
|
-
|
|
54
51
|
def _download(site: dict, start_date: str, end_date: str):
|
|
55
52
|
return download(
|
|
56
53
|
TERM_ID,
|
|
@@ -63,6 +60,13 @@ def _download(site: dict, start_date: str, end_date: str):
|
|
|
63
60
|
)
|
|
64
61
|
|
|
65
62
|
|
|
63
|
+
def _value_at(site: dict, start_date: str, end_date: str):
|
|
64
|
+
# collection is in meters, convert to millimeters
|
|
65
|
+
factor = 1000
|
|
66
|
+
value = _download(site, start_date, end_date)
|
|
67
|
+
return (value * factor, start_date[0:7]) if value is not None else None
|
|
68
|
+
|
|
69
|
+
|
|
66
70
|
def _run(site: dict, years: list):
|
|
67
71
|
# fetch from first year to last
|
|
68
72
|
years = range(years[0], years[-1] + 1) if len(years) > 1 else years
|
|
@@ -73,10 +77,8 @@ def _run(site: dict, years: list):
|
|
|
73
77
|
for month in range(1, 13)
|
|
74
78
|
] for year in years
|
|
75
79
|
])
|
|
76
|
-
values = non_empty_list([
|
|
77
|
-
|
|
78
|
-
])
|
|
79
|
-
return _measurement(site, [v for v, d in values], [d for v, d in values])
|
|
80
|
+
values = non_empty_list([_value_at(site, start_date, end_date) for start_date, end_date in dates])
|
|
81
|
+
return [_measurement(site, [v for v, d in values], [d for v, d in values])] if values else []
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
def run(site: dict):
|
|
@@ -9,7 +9,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
9
9
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
10
10
|
from hestia_earth.models.utils.source import get_source
|
|
11
11
|
from hestia_earth.models.utils.site import related_years
|
|
12
|
-
from .utils import
|
|
12
|
+
from .utils import to_celcius, download, has_geospatial_data, should_download
|
|
13
13
|
from . import MODEL
|
|
14
14
|
|
|
15
15
|
REQUIREMENTS = {
|
|
@@ -49,9 +49,6 @@ def _measurement(site: dict, value: float, year: int):
|
|
|
49
49
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def _to_celcius(kelvin_value: int): return kelvin_value - KELVIN_0 if kelvin_value else None
|
|
53
|
-
|
|
54
|
-
|
|
55
52
|
def _download(site: dict, year: int):
|
|
56
53
|
return download(
|
|
57
54
|
TERM_ID,
|
|
@@ -64,7 +61,7 @@ def _download(site: dict, year: int):
|
|
|
64
61
|
|
|
65
62
|
|
|
66
63
|
def _run(site: dict, year: int):
|
|
67
|
-
value =
|
|
64
|
+
value = to_celcius(_download(site, year))
|
|
68
65
|
return _measurement(site, value, year) if value else None
|
|
69
66
|
|
|
70
67
|
|
|
@@ -3,9 +3,8 @@ from hestia_earth.schema import MeasurementMethodClassification
|
|
|
3
3
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
4
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
5
5
|
from hestia_earth.models.utils.source import get_source
|
|
6
|
-
from .utils import download, has_geospatial_data, should_download
|
|
6
|
+
from .utils import to_celcius, download, has_geospatial_data, should_download
|
|
7
7
|
from . import MODEL
|
|
8
|
-
from .temperatureAnnual import _to_celcius
|
|
9
8
|
|
|
10
9
|
REQUIREMENTS = {
|
|
11
10
|
"Site": {
|
|
@@ -50,7 +49,7 @@ def _measurement(site: dict, value: float):
|
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
def _run(site: dict):
|
|
53
|
-
value =
|
|
52
|
+
value = to_celcius(download(TERM_ID, site, EE_PARAMS))
|
|
54
53
|
return [_measurement(site, value)] if value is not None else []
|
|
55
54
|
|
|
56
55
|
|
|
@@ -10,7 +10,7 @@ from hestia_earth.models.utils import first_day_of_month, last_day_of_month
|
|
|
10
10
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
11
11
|
from hestia_earth.models.utils.source import get_source
|
|
12
12
|
from hestia_earth.models.utils.site import related_years
|
|
13
|
-
from .utils import
|
|
13
|
+
from .utils import to_celcius, download, has_geospatial_data, should_download
|
|
14
14
|
from . import MODEL
|
|
15
15
|
|
|
16
16
|
REQUIREMENTS = {
|
|
@@ -48,9 +48,6 @@ def _measurement(site: dict, value: list, dates: list):
|
|
|
48
48
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def _to_celcius(kelvin_value: int): return kelvin_value - KELVIN_0 if kelvin_value else None
|
|
52
|
-
|
|
53
|
-
|
|
54
51
|
def _download(site: dict, start_date: str, end_date: str):
|
|
55
52
|
return download(
|
|
56
53
|
TERM_ID,
|
|
@@ -63,6 +60,11 @@ def _download(site: dict, start_date: str, end_date: str):
|
|
|
63
60
|
)
|
|
64
61
|
|
|
65
62
|
|
|
63
|
+
def _value_at(site: dict, start_date: str, end_date: str):
|
|
64
|
+
value = _download(site, start_date, end_date)
|
|
65
|
+
return (to_celcius(value), start_date[0:7]) if value is not None else None
|
|
66
|
+
|
|
67
|
+
|
|
66
68
|
def _run(site: dict, years: list):
|
|
67
69
|
# fetch from first year to last
|
|
68
70
|
years = range(years[0], years[-1] + 1) if len(years) > 1 else years
|
|
@@ -73,10 +75,8 @@ def _run(site: dict, years: list):
|
|
|
73
75
|
for month in range(1, 13)
|
|
74
76
|
] for year in years
|
|
75
77
|
])
|
|
76
|
-
values = non_empty_list([
|
|
77
|
-
|
|
78
|
-
])
|
|
79
|
-
return _measurement(site, [v for v, d in values], [d for v, d in values])
|
|
78
|
+
values = non_empty_list([_value_at(site, start_date, end_date) for start_date, end_date in dates])
|
|
79
|
+
return [_measurement(site, [v for v, d in values], [d for v, d in values])] if values else []
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
def run(site: dict):
|
|
@@ -23,6 +23,9 @@ GEOPANDAS_COLLECTION_NAME = {
|
|
|
23
23
|
KELVIN_0 = 273.15
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def to_celcius(kelvin_value: int): return kelvin_value - KELVIN_0 if kelvin_value else None
|
|
27
|
+
|
|
28
|
+
|
|
26
29
|
def use_geopandas(): return os.getenv('HEE_USE_GEOPANDAS', 'false') == 'true'
|
|
27
30
|
|
|
28
31
|
|
|
@@ -139,7 +142,9 @@ def _get_cached_data(term: str, site: dict, data: dict):
|
|
|
139
142
|
data.get('end_date')
|
|
140
143
|
]))
|
|
141
144
|
# data can be grouped by year when required
|
|
142
|
-
value = cache.get(cache_sub_key) if
|
|
145
|
+
value = cache.get(cache_sub_key) if (
|
|
146
|
+
isinstance(cache, dict) and cache_sub_key in cache and cache is not None
|
|
147
|
+
) else cache
|
|
143
148
|
if value is not None:
|
|
144
149
|
debugValues(site, model=MODEL, term=term, value_from_cache=value)
|
|
145
150
|
return value
|
|
@@ -46,7 +46,6 @@ from hestia_earth.models.utils.term import (
|
|
|
46
46
|
get_cover_crop_property_terms,
|
|
47
47
|
get_crop_residue_incorporated_or_left_on_field_terms,
|
|
48
48
|
get_irrigated_terms,
|
|
49
|
-
get_long_fallow_land_cover_terms,
|
|
50
49
|
get_residue_removed_or_burnt_terms,
|
|
51
50
|
get_upland_rice_crop_terms,
|
|
52
51
|
get_upland_rice_land_cover_terms
|
|
@@ -610,25 +609,26 @@ A dictionary mapping IPCC soil categories to corresponding soil type and USDA so
|
|
|
610
609
|
`"IPCC_SOIL_CATEGORY"` column.
|
|
611
610
|
"""
|
|
612
611
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
IpccLandUseCategory.ANNUAL_CROPS_WET: SiteSiteType.CROPLAND.value,
|
|
618
|
-
IpccLandUseCategory.ANNUAL_CROPS: SiteSiteType.CROPLAND.value,
|
|
619
|
-
IpccLandUseCategory.SET_ASIDE: SiteSiteType.CROPLAND.value,
|
|
620
|
-
IpccLandUseCategory.FOREST: SiteSiteType.FOREST.value,
|
|
621
|
-
IpccLandUseCategory.NATIVE: SiteSiteType.OTHER_NATURAL_VEGETATION.value
|
|
612
|
+
SITE_TYPE_TO_IPCC_LAND_USE_CATEGORY = {
|
|
613
|
+
SiteSiteType.PERMANENT_PASTURE.value: IpccLandUseCategory.GRASSLAND,
|
|
614
|
+
SiteSiteType.FOREST.value: IpccLandUseCategory.FOREST,
|
|
615
|
+
SiteSiteType.OTHER_NATURAL_VEGETATION.value: IpccLandUseCategory.NATIVE
|
|
622
616
|
}
|
|
623
617
|
"""
|
|
624
|
-
A dictionary mapping IPCC land use categories
|
|
618
|
+
A dictionary mapping site types to corresponding IPCC land use categories.
|
|
625
619
|
"""
|
|
626
620
|
|
|
627
621
|
IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_LOOKUP_VALUE = {
|
|
622
|
+
IpccLandUseCategory.GRASSLAND: "Grassland",
|
|
628
623
|
IpccLandUseCategory.PERENNIAL_CROPS: "Perennial crops",
|
|
629
624
|
IpccLandUseCategory.PADDY_RICE_CULTIVATION: "Paddy rice cultivation",
|
|
630
625
|
IpccLandUseCategory.ANNUAL_CROPS_WET: "Annual crops",
|
|
631
|
-
IpccLandUseCategory.ANNUAL_CROPS: "Annual crops"
|
|
626
|
+
IpccLandUseCategory.ANNUAL_CROPS: "Annual crops",
|
|
627
|
+
IpccLandUseCategory.SET_ASIDE: [
|
|
628
|
+
"Annual crops", "Paddy rice cultivation", "Perennial crops", "Set aside"
|
|
629
|
+
],
|
|
630
|
+
IpccLandUseCategory.FOREST: "Forest",
|
|
631
|
+
IpccLandUseCategory.NATIVE: "Native"
|
|
632
632
|
}
|
|
633
633
|
"""
|
|
634
634
|
A dictionary mapping IPCC land use categories to corresponding land cover lookup values in the
|
|
@@ -2525,7 +2525,7 @@ def _has_irrigation(water_regime_nodes: list[dict]) -> bool:
|
|
|
2525
2525
|
|
|
2526
2526
|
Parameters
|
|
2527
2527
|
----------
|
|
2528
|
-
water_regime_nodes :
|
|
2528
|
+
water_regime_nodes : list[dict]
|
|
2529
2529
|
List of water regime nodes to be checked.
|
|
2530
2530
|
|
|
2531
2531
|
Returns
|
|
@@ -2542,13 +2542,13 @@ def _has_irrigation(water_regime_nodes: list[dict]) -> bool:
|
|
|
2542
2542
|
|
|
2543
2543
|
def _has_long_fallow(land_cover_nodes: list[dict]) -> bool:
|
|
2544
2544
|
"""
|
|
2545
|
-
Check if long fallow terms
|
|
2545
|
+
Check if long fallow terms are present in the land cover nodes.
|
|
2546
2546
|
|
|
2547
2547
|
n.b., a super majority of the site area must be under long fallow for it to be classified as set aside.
|
|
2548
2548
|
|
|
2549
2549
|
Parameters
|
|
2550
2550
|
----------
|
|
2551
|
-
land_cover_nodes :
|
|
2551
|
+
land_cover_nodes : list[dict]
|
|
2552
2552
|
List of land cover nodes to be checked.
|
|
2553
2553
|
|
|
2554
2554
|
Returns
|
|
@@ -2556,9 +2556,12 @@ def _has_long_fallow(land_cover_nodes: list[dict]) -> bool:
|
|
|
2556
2556
|
bool
|
|
2557
2557
|
`True` if long fallow is present, `False` otherwise.
|
|
2558
2558
|
"""
|
|
2559
|
-
|
|
2559
|
+
LOOKUP = LOOKUPS["landCover"][0]
|
|
2560
|
+
TARGET_LOOKUP_VALUE = "Set aside"
|
|
2561
|
+
return cumulative_nodes_lookup_match(
|
|
2560
2562
|
land_cover_nodes,
|
|
2561
|
-
|
|
2563
|
+
lookup=LOOKUP,
|
|
2564
|
+
target_lookup_values=TARGET_LOOKUP_VALUE,
|
|
2562
2565
|
cumulative_threshold=SUPER_MAJORITY_AREA_THRESHOLD
|
|
2563
2566
|
) or cumulative_nodes_match(
|
|
2564
2567
|
lambda node: get_node_property(node, LONG_FALLOW_CROP_TERM_ID, False).get("value", 0),
|
|
@@ -2573,7 +2576,7 @@ def _has_upland_rice(land_cover_nodes: list[dict]) -> bool:
|
|
|
2573
2576
|
|
|
2574
2577
|
Parameters
|
|
2575
2578
|
----------
|
|
2576
|
-
land_cover_nodes :
|
|
2579
|
+
land_cover_nodes : list[dict]
|
|
2577
2580
|
List of land cover nodes to be checked.
|
|
2578
2581
|
|
|
2579
2582
|
Returns
|
|
@@ -2589,63 +2592,39 @@ def _has_upland_rice(land_cover_nodes: list[dict]) -> bool:
|
|
|
2589
2592
|
|
|
2590
2593
|
|
|
2591
2594
|
IPCC_LAND_USE_CATEGORY_TO_VALIDATION_KWARGS = {
|
|
2595
|
+
IpccLandUseCategory.ANNUAL_CROPS_WET: {"has_wetland_soils"},
|
|
2592
2596
|
IpccLandUseCategory.SET_ASIDE: {"has_long_fallow"},
|
|
2593
|
-
IpccLandUseCategory.ANNUAL_CROPS_WET: {"has_wetland_soils"}
|
|
2594
2597
|
}
|
|
2595
2598
|
"""
|
|
2596
|
-
Keyword arguments that need to be
|
|
2599
|
+
Keyword arguments that need to be validated in addition to the `landCover` lookup match for specific
|
|
2600
|
+
`IpccLandUseCategory`s.
|
|
2597
2601
|
"""
|
|
2598
2602
|
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
----------
|
|
2606
|
-
key : IpccLandUseCategory
|
|
2607
|
-
The IPCC land use category to check.
|
|
2608
|
-
site_type : str
|
|
2609
|
-
The site type to check.
|
|
2610
|
-
|
|
2611
|
-
Keyword Args
|
|
2612
|
-
------------
|
|
2613
|
-
has_long_fallow : bool
|
|
2614
|
-
Indicates whether long fallow is present on more than 30% of the site.
|
|
2615
|
-
has_wetland_soils : bool
|
|
2616
|
-
Indicates whether wetland soils are present to more than 30% of the site.
|
|
2617
|
-
|
|
2618
|
-
Returns
|
|
2619
|
-
-------
|
|
2620
|
-
bool
|
|
2621
|
-
`True` if the conditions match the specified land use category, `False` otherwise.
|
|
2622
|
-
|
|
2623
|
-
"""
|
|
2624
|
-
target_site_type = IPCC_LAND_USE_CATEGORY_TO_SITE_TYPE.get(key, None)
|
|
2625
|
-
validation_kwargs = IPCC_LAND_USE_CATEGORY_TO_VALIDATION_KWARGS.get(key, set())
|
|
2626
|
-
valid_kwargs = all(v for k, v in kwargs.items() if k in validation_kwargs)
|
|
2627
|
-
return site_type == target_site_type and valid_kwargs
|
|
2603
|
+
IPCC_LAND_USE_CATEGORY_TO_OVERRIDE_KWARGS = {
|
|
2604
|
+
IpccLandUseCategory.PADDY_RICE_CULTIVATION: {"has_irrigated_upland_rice"}
|
|
2605
|
+
}
|
|
2606
|
+
"""
|
|
2607
|
+
Keyword arguments that can override the `landCover` lookup match for specific `IpccLandUseCategory`s.
|
|
2608
|
+
"""
|
|
2628
2609
|
|
|
2629
2610
|
|
|
2630
|
-
def
|
|
2631
|
-
*, key: IpccLandUseCategory, site_type: str, land_cover_nodes: list[dict], **kwargs
|
|
2632
|
-
) -> bool:
|
|
2611
|
+
def _check_ipcc_land_use_category(*, key: IpccLandUseCategory, land_cover_nodes: list[dict], **kwargs) -> bool:
|
|
2633
2612
|
"""
|
|
2634
|
-
Check if the
|
|
2635
|
-
|
|
2636
|
-
This function is special case of `_check_ipcc_land_use_category`.
|
|
2613
|
+
Check if the land cover nodes and keyword args satisfy the requirements for the given key.
|
|
2637
2614
|
|
|
2638
2615
|
Parameters
|
|
2639
2616
|
----------
|
|
2640
2617
|
key : IpccLandUseCategory
|
|
2641
2618
|
The IPCC land use category to check.
|
|
2642
|
-
|
|
2643
|
-
|
|
2619
|
+
land_cover_nodes : list[dict]
|
|
2620
|
+
List of land cover nodes to be checked.
|
|
2644
2621
|
|
|
2645
2622
|
Keyword Args
|
|
2646
2623
|
------------
|
|
2624
|
+
has_irrigated_upland_rice : bool
|
|
2625
|
+
Indicates whether irrigated upland rice is present on more than 30% of the site.
|
|
2647
2626
|
has_long_fallow : bool
|
|
2648
|
-
Indicates whether long fallow is present on more than
|
|
2627
|
+
Indicates whether long fallow is present on more than 70% of the site.
|
|
2649
2628
|
has_wetland_soils : bool
|
|
2650
2629
|
Indicates whether wetland soils are present to more than 30% of the site.
|
|
2651
2630
|
|
|
@@ -2662,48 +2641,23 @@ def _check_cropland_land_use_category(
|
|
|
2662
2641
|
target_lookup_values=target_lookup_values,
|
|
2663
2642
|
cumulative_threshold=MIN_AREA_THRESHOLD
|
|
2664
2643
|
)
|
|
2665
|
-
return _check_ipcc_land_use_category(key=key, site_type=site_type, **kwargs) and valid_lookup
|
|
2666
2644
|
|
|
2645
|
+
validation_kwargs = IPCC_LAND_USE_CATEGORY_TO_VALIDATION_KWARGS.get(key, set())
|
|
2646
|
+
valid_kwargs = all(v for k, v in kwargs.items() if k in validation_kwargs)
|
|
2667
2647
|
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
) -> bool:
|
|
2671
|
-
"""
|
|
2672
|
-
Check if the site type and land cover nodes match the target conditions for a cropland IpccLandUseCategory.
|
|
2648
|
+
override_kwargs = IPCC_LAND_USE_CATEGORY_TO_OVERRIDE_KWARGS.get(key, set())
|
|
2649
|
+
valid_override = any(v for k, v in kwargs.items() if k in override_kwargs)
|
|
2673
2650
|
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
Parameters
|
|
2677
|
-
----------
|
|
2678
|
-
key : IpccLandUseCategory
|
|
2679
|
-
The IPCC land use category to check.
|
|
2680
|
-
site_type : str
|
|
2681
|
-
The site type to check.
|
|
2682
|
-
|
|
2683
|
-
Keyword Args
|
|
2684
|
-
------------
|
|
2685
|
-
has_irrigated_upland_rice : bool
|
|
2686
|
-
Indicates whether irrigated upland rice is present on more than 30% of the site.
|
|
2687
|
-
has_long_fallow : bool
|
|
2688
|
-
Indicates whether long fallow is present on more than 30% of the site.
|
|
2689
|
-
has_wetland_soils : bool
|
|
2690
|
-
Indicates whether wetland soils are present to more than 30% of the site.
|
|
2691
|
-
|
|
2692
|
-
Returns
|
|
2693
|
-
-------
|
|
2694
|
-
bool
|
|
2695
|
-
`True` if the conditions match the specified land use category, `False` otherwise.
|
|
2696
|
-
"""
|
|
2697
|
-
return _check_cropland_land_use_category(key=key, site_type=site_type, **kwargs) or has_irrigated_upland_rice
|
|
2651
|
+
return (valid_lookup and valid_kwargs) or valid_override
|
|
2698
2652
|
|
|
2699
2653
|
|
|
2700
2654
|
LAND_USE_CATEGORY_DECISION_TREE = {
|
|
2701
2655
|
IpccLandUseCategory.GRASSLAND: _check_ipcc_land_use_category,
|
|
2702
2656
|
IpccLandUseCategory.SET_ASIDE: _check_ipcc_land_use_category,
|
|
2703
|
-
IpccLandUseCategory.PERENNIAL_CROPS:
|
|
2704
|
-
IpccLandUseCategory.PADDY_RICE_CULTIVATION:
|
|
2705
|
-
IpccLandUseCategory.ANNUAL_CROPS_WET:
|
|
2706
|
-
IpccLandUseCategory.ANNUAL_CROPS:
|
|
2657
|
+
IpccLandUseCategory.PERENNIAL_CROPS: _check_ipcc_land_use_category,
|
|
2658
|
+
IpccLandUseCategory.PADDY_RICE_CULTIVATION: _check_ipcc_land_use_category,
|
|
2659
|
+
IpccLandUseCategory.ANNUAL_CROPS_WET: _check_ipcc_land_use_category,
|
|
2660
|
+
IpccLandUseCategory.ANNUAL_CROPS: _check_ipcc_land_use_category,
|
|
2707
2661
|
IpccLandUseCategory.FOREST: _check_ipcc_land_use_category,
|
|
2708
2662
|
IpccLandUseCategory.NATIVE: _check_ipcc_land_use_category,
|
|
2709
2663
|
IpccLandUseCategory.OTHER: _check_ipcc_land_use_category
|
|
@@ -2712,21 +2666,19 @@ LAND_USE_CATEGORY_DECISION_TREE = {
|
|
|
2712
2666
|
A decision tree mapping IPCC soil categories to corresponding check functions.
|
|
2713
2667
|
|
|
2714
2668
|
Key: IpccLandUseCategory
|
|
2715
|
-
Value: Corresponding function for checking the match of the given land use category based on
|
|
2716
|
-
and
|
|
2669
|
+
Value: Corresponding function for checking the match of the given land use category based on land cover nodes
|
|
2670
|
+
and additional kwargs.
|
|
2717
2671
|
"""
|
|
2718
2672
|
|
|
2719
2673
|
|
|
2720
2674
|
def _assign_ipcc_land_use_category(
|
|
2721
|
-
|
|
2675
|
+
management_nodes: list[dict], ipcc_soil_category: IpccSoilCategory,
|
|
2722
2676
|
) -> IpccLandUseCategory:
|
|
2723
2677
|
"""
|
|
2724
|
-
Assigns IPCC land use category based on
|
|
2678
|
+
Assigns IPCC land use category based on management nodes and soil category.
|
|
2725
2679
|
|
|
2726
2680
|
Parameters
|
|
2727
2681
|
----------
|
|
2728
|
-
site_type : str
|
|
2729
|
-
The type of the site.
|
|
2730
2682
|
management_nodes : list[dict]
|
|
2731
2683
|
List of management nodes.
|
|
2732
2684
|
ipcc_soil_category : IpccSoilCategory
|
|
@@ -2749,14 +2701,13 @@ def _assign_ipcc_land_use_category(
|
|
|
2749
2701
|
has_long_fallow = _has_long_fallow(land_cover_nodes)
|
|
2750
2702
|
has_wetland_soils = ipcc_soil_category is IpccSoilCategory.WETLAND_SOILS
|
|
2751
2703
|
|
|
2752
|
-
should_run = bool(
|
|
2704
|
+
should_run = bool(land_cover_nodes)
|
|
2753
2705
|
|
|
2754
2706
|
return next(
|
|
2755
2707
|
(
|
|
2756
2708
|
key for key in DECISION_TREE
|
|
2757
2709
|
if DECISION_TREE[key](
|
|
2758
2710
|
key=key,
|
|
2759
|
-
site_type=site_type,
|
|
2760
2711
|
land_cover_nodes=land_cover_nodes,
|
|
2761
2712
|
has_long_fallow=has_long_fallow,
|
|
2762
2713
|
has_irrigated_upland_rice=has_irrigated_upland_rice,
|
|
@@ -2780,7 +2731,7 @@ def _check_grassland_ipcc_management_category(
|
|
|
2780
2731
|
----------
|
|
2781
2732
|
key : IpccManagementCategory
|
|
2782
2733
|
The IPCC management category to check.
|
|
2783
|
-
land_cover_nodes :
|
|
2734
|
+
land_cover_nodes : list[dict]
|
|
2784
2735
|
List of land cover nodes to be checked.
|
|
2785
2736
|
|
|
2786
2737
|
Returns
|
|
@@ -2806,7 +2757,7 @@ def _check_tillage_ipcc_management_category(
|
|
|
2806
2757
|
----------
|
|
2807
2758
|
key : IpccManagementCategory
|
|
2808
2759
|
The IPCC management category to check.
|
|
2809
|
-
tillage_nodes :
|
|
2760
|
+
tillage_nodes : list[dict]
|
|
2810
2761
|
List of tillage nodes to be checked.
|
|
2811
2762
|
|
|
2812
2763
|
Returns
|
|
@@ -3783,11 +3734,15 @@ def _should_run_inventory_year_tier_2(group: dict) -> bool:
|
|
|
3783
3734
|
def _get_grouped_climate_measurements(grouped_measurements: dict) -> dict:
|
|
3784
3735
|
return {
|
|
3785
3736
|
year: {
|
|
3786
|
-
_InventoryKey.TEMP_MONTHLY:
|
|
3787
|
-
|
|
3737
|
+
_InventoryKey.TEMP_MONTHLY: non_empty_list(
|
|
3738
|
+
find_term_match(measurements, TEMPERATURE_MONTHLY_TERM_ID, {}).get("value", [])
|
|
3739
|
+
),
|
|
3740
|
+
_InventoryKey.PRECIP_MONTHLY: non_empty_list(
|
|
3788
3741
|
find_term_match(measurements, PRECIPITATION_MONTHLY_TERM_ID, {}).get("value", [])
|
|
3789
3742
|
),
|
|
3790
|
-
_InventoryKey.PET_MONTHLY:
|
|
3743
|
+
_InventoryKey.PET_MONTHLY: non_empty_list(
|
|
3744
|
+
find_term_match(measurements, PET_MONTHLY_TERM_ID, {}).get("value", [])
|
|
3745
|
+
)
|
|
3791
3746
|
} for year, measurements in grouped_measurements.items()
|
|
3792
3747
|
}
|
|
3793
3748
|
|
|
@@ -3917,15 +3872,19 @@ def _build_inventory_tier_1(
|
|
|
3917
3872
|
eco_climate_zone = _get_eco_climate_zone(measurement_nodes)
|
|
3918
3873
|
ipcc_soil_category = _assign_ipcc_soil_category(measurement_nodes)
|
|
3919
3874
|
soc_ref = _retrieve_soc_ref(eco_climate_zone, ipcc_soil_category)
|
|
3875
|
+
grouped_management = group_nodes_by_year(management_nodes)
|
|
3876
|
+
|
|
3877
|
+
# If no `landCover` nodes in `site.management` use `site.siteType` to assign static `IpccLandUseCategory`
|
|
3878
|
+
run_with_site_type = len(filter_list_term_type(management_nodes, [TermTermType.LANDCOVER])) == 0
|
|
3879
|
+
site_type_ipcc_land_use_category = SITE_TYPE_TO_IPCC_LAND_USE_CATEGORY.get(site_type, IpccLandUseCategory.OTHER)
|
|
3920
3880
|
|
|
3921
3881
|
grouped_management = group_nodes_by_year(management_nodes)
|
|
3922
3882
|
|
|
3923
3883
|
grouped_land_use_categories = {
|
|
3924
3884
|
year: {
|
|
3925
|
-
_InventoryKey.LU_CATEGORY:
|
|
3926
|
-
|
|
3927
|
-
nodes,
|
|
3928
|
-
ipcc_soil_category
|
|
3885
|
+
_InventoryKey.LU_CATEGORY: (
|
|
3886
|
+
site_type_ipcc_land_use_category if run_with_site_type
|
|
3887
|
+
else _assign_ipcc_land_use_category(nodes, ipcc_soil_category)
|
|
3929
3888
|
)
|
|
3930
3889
|
} for year, nodes in grouped_management.items()
|
|
3931
3890
|
}
|
|
@@ -3963,7 +3922,8 @@ def _build_inventory_tier_1(
|
|
|
3963
3922
|
kwargs = {
|
|
3964
3923
|
"eco_climate_zone": eco_climate_zone,
|
|
3965
3924
|
"ipcc_soil_category": ipcc_soil_category,
|
|
3966
|
-
"
|
|
3925
|
+
"run_with_site_type": run_with_site_type,
|
|
3926
|
+
"soc_ref": soc_ref
|
|
3967
3927
|
}
|
|
3968
3928
|
|
|
3969
3929
|
return inventory, kwargs
|