hestia-earth-models 0.62.0__py3-none-any.whl → 0.62.1__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/blonkConsultants2016/utils.py +3 -2
- hestia_earth/models/cycle/post_checks/__init__.py +3 -2
- hestia_earth/models/cycle/post_checks/otherSites.py +40 -0
- hestia_earth/models/cycle/pre_checks/__init__.py +2 -1
- hestia_earth/models/cycle/pre_checks/otherSites.py +42 -0
- hestia_earth/models/cycle/pre_checks/site.py +1 -1
- hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
- hestia_earth/models/emepEea2019/utils.py +4 -3
- hestia_earth/models/geospatialDatabase/heavyWinterPrecipitation.py +1 -1
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +6 -6
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +30 -4
- hestia_earth/models/ipcc2019/n2OToAirExcretaDirect.py +6 -2
- hestia_earth/models/ipcc2019/n2OToAirExcretaIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +4 -2
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +2 -1
- hestia_earth/models/ipcc2019/pastureGrass.py +3 -3
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +41 -41
- hestia_earth/models/mocking/search-results.json +89 -89
- hestia_earth/models/schererPfister2015/utils.py +2 -2
- hestia_earth/models/site/brackishWater.py +1 -1
- hestia_earth/models/site/flowingWater.py +1 -1
- hestia_earth/models/site/freshWater.py +1 -1
- hestia_earth/models/site/management.py +29 -11
- hestia_earth/models/site/pre_checks/cache_sources.py +9 -13
- hestia_earth/models/site/salineWater.py +1 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +12 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +12 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +11 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +11 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +12 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +12 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +12 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +12 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +11 -1
- hestia_earth/models/utils/blank_node.py +106 -110
- hestia_earth/models/utils/constant.py +2 -0
- hestia_earth/models/utils/lookup.py +19 -6
- hestia_earth/models/utils/source.py +1 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.1.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.1.dist-info}/RECORD +58 -53
- tests/models/cycle/post_checks/test_otherSites.py +15 -0
- tests/models/cycle/pre_checks/test_otherSites.py +21 -0
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +5 -3
- tests/models/ipcc2019/test_organicCarbonPerHa.py +1 -0
- tests/models/site/pre_checks/test_cache_sources.py +6 -10
- tests/models/site/test_management.py +162 -2
- tests/models/utils/test_blank_node.py +0 -281
- tests/models/utils/test_lookup.py +10 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.1.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.1.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.1.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Pre Checks Cache Sources
|
|
3
3
|
|
|
4
|
-
This model caches the sources of all models.
|
|
4
|
+
This model caches the sources of all Site models.
|
|
5
5
|
"""
|
|
6
6
|
from hestia_earth.models.log import debugValues
|
|
7
7
|
from hestia_earth.models.utils import CACHE_KEY, cached_value
|
|
@@ -15,24 +15,20 @@ RETURNS = {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def _run(site: dict):
|
|
19
19
|
sources = find_sources()
|
|
20
|
-
|
|
20
|
+
debugValues(site, sources=';'.join([str(title) for title in sources.keys()]))
|
|
21
|
+
return sources
|
|
21
22
|
|
|
22
|
-
debugValues(site,
|
|
23
|
-
sources=';'.join([str(title) for title in sources.keys()]),
|
|
24
|
-
has_cache=has_cache)
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
])
|
|
30
|
-
return should_run, sources
|
|
24
|
+
def _should_run(site: dict):
|
|
25
|
+
has_cache = cached_value(site, CACHE_SOURCES_KEY)
|
|
26
|
+
return not bool(has_cache)
|
|
31
27
|
|
|
32
28
|
|
|
33
29
|
def run(site: dict):
|
|
34
|
-
should_run
|
|
30
|
+
should_run = _should_run(site)
|
|
35
31
|
return {
|
|
36
32
|
**site,
|
|
37
|
-
CACHE_KEY: cached_value(site) | {CACHE_SOURCES_KEY:
|
|
33
|
+
CACHE_KEY: cached_value(site) | {CACHE_SOURCES_KEY: _run(site)}
|
|
38
34
|
} if should_run else site
|
|
@@ -23,7 +23,7 @@ TERM_ID = 'salineWater'
|
|
|
23
23
|
|
|
24
24
|
def _measurement():
|
|
25
25
|
data = _new_measurement(TERM_ID)
|
|
26
|
-
data['value'] = [
|
|
26
|
+
data['value'] = [True]
|
|
27
27
|
data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
|
|
28
28
|
return data
|
|
29
29
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .n2OToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -59,5 +61,13 @@ def _run(cycle: dict, content_list_of_items: list, N_total: float):
|
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
def run(cycle: dict):
|
|
62
|
-
|
|
64
|
+
default_should_run, N_total, content_list_of_items = _should_run(cycle, TERM_ID, TIER)
|
|
65
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.CROPRESIDUE)
|
|
66
|
+
|
|
67
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
68
|
+
term_type_cropResidue_complete=term_type_complete)
|
|
69
|
+
|
|
70
|
+
should_run = all([default_should_run, term_type_complete])
|
|
71
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
72
|
+
|
|
63
73
|
return _run(cycle, content_list_of_items, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .n2OToAirSoilFlux import _get_value, _should_run
|
|
6
8
|
from . import MODEL
|
|
@@ -66,5 +68,13 @@ def _run(cycle: dict, content_list_of_items: list, N_total: float):
|
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
def run(cycle: dict):
|
|
69
|
-
|
|
71
|
+
default_should_run, N_total, content_list_of_items = _should_run(cycle, TERM_ID, TIER)
|
|
72
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.EXCRETA)
|
|
73
|
+
|
|
74
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
75
|
+
term_type_excreta_complete=term_type_complete)
|
|
76
|
+
|
|
77
|
+
should_run = all([default_should_run, term_type_complete])
|
|
78
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
79
|
+
|
|
70
80
|
return _run(cycle, content_list_of_items, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
5
7
|
from .n2OToAirSoilFlux import _get_value, _should_run
|
|
6
8
|
from . import MODEL
|
|
@@ -69,5 +71,13 @@ def _run(cycle: dict, content_list_of_items: list, N_total: float):
|
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
def run(cycle: dict):
|
|
72
|
-
|
|
74
|
+
default_should_run, N_total, content_list_of_items = _should_run(cycle, TERM_ID, TIER)
|
|
75
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
76
|
+
|
|
77
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
78
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
79
|
+
|
|
80
|
+
should_run = all([default_should_run, term_type_complete])
|
|
81
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
82
|
+
|
|
73
83
|
return _run(cycle, content_list_of_items, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
5
7
|
from .n2OToAirSoilFlux import _get_value, _should_run
|
|
6
8
|
from . import MODEL
|
|
@@ -69,5 +71,13 @@ def _run(cycle: dict, content_list_of_items: list, N_total: float):
|
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
def run(cycle: dict):
|
|
72
|
-
|
|
74
|
+
default_should_run, N_total, content_list_of_items = _should_run(cycle, TERM_ID, TIER)
|
|
75
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
76
|
+
|
|
77
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
78
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
79
|
+
|
|
80
|
+
should_run = all([default_should_run, term_type_complete])
|
|
81
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
82
|
+
|
|
73
83
|
return _run(cycle, content_list_of_items, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -54,5 +56,13 @@ def _run(cycle: dict, ecoClimateZone: str, nitrogenContent: float, N_total: floa
|
|
|
54
56
|
|
|
55
57
|
|
|
56
58
|
def run(cycle: dict):
|
|
57
|
-
|
|
59
|
+
default_should_run, ecoClimateZone, nitrogenContent, N_total = _should_run(cycle, TERM_ID, TIER)
|
|
60
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.CROPRESIDUE)
|
|
61
|
+
|
|
62
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
63
|
+
term_type_cropResidue_complete=term_type_complete)
|
|
64
|
+
|
|
65
|
+
should_run = all([default_should_run, term_type_complete])
|
|
66
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
67
|
+
|
|
58
68
|
return _run(cycle, ecoClimateZone, nitrogenContent, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -61,5 +63,13 @@ def _run(cycle: dict, ecoClimateZone: str, nitrogenContent: float, N_total: floa
|
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
def run(cycle: dict):
|
|
64
|
-
|
|
66
|
+
default_should_run, ecoClimateZone, nitrogenContent, N_total = _should_run(cycle, TERM_ID, TIER)
|
|
67
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.EXCRETA)
|
|
68
|
+
|
|
69
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
70
|
+
term_type_excreta_complete=term_type_complete)
|
|
71
|
+
|
|
72
|
+
should_run = all([default_should_run, term_type_complete])
|
|
73
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
74
|
+
|
|
65
75
|
return _run(cycle, ecoClimateZone, nitrogenContent, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -64,5 +66,13 @@ def _run(cycle: dict, ecoClimateZone: str, nitrogenContent: float, N_total: floa
|
|
|
64
66
|
|
|
65
67
|
|
|
66
68
|
def run(cycle: dict):
|
|
67
|
-
|
|
69
|
+
default_should_run, ecoClimateZone, nitrogenContent, N_total = _should_run(cycle, TERM_ID, TIER)
|
|
70
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
71
|
+
|
|
72
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
73
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
74
|
+
|
|
75
|
+
should_run = all([default_should_run, term_type_complete])
|
|
76
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
77
|
+
|
|
68
78
|
return _run(cycle, ecoClimateZone, nitrogenContent, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -64,5 +66,13 @@ def _run(cycle: dict, ecoClimateZone: str, nitrogenContent: float, N_total: floa
|
|
|
64
66
|
|
|
65
67
|
|
|
66
68
|
def run(cycle: dict):
|
|
67
|
-
|
|
69
|
+
default_should_run, ecoClimateZone, nitrogenContent, N_total = _should_run(cycle, TERM_ID, TIER)
|
|
70
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
71
|
+
|
|
72
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
73
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
74
|
+
|
|
75
|
+
should_run = all([default_should_run, term_type_complete])
|
|
76
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
77
|
+
|
|
68
78
|
return _run(cycle, ecoClimateZone, nitrogenContent, N_total) if should_run else []
|
hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -51,5 +53,13 @@ def _run(cycle: dict, country_id: str, N_total: float):
|
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
def run(cycle: dict):
|
|
54
|
-
|
|
56
|
+
default_should_run, country_id, N_total, *args = _should_run(cycle, TERM_ID, TIER)
|
|
57
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.CROPRESIDUE)
|
|
58
|
+
|
|
59
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
60
|
+
term_type_cropResidue_complete=term_type_complete)
|
|
61
|
+
|
|
62
|
+
should_run = all([default_should_run, term_type_complete])
|
|
63
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
64
|
+
|
|
55
65
|
return _run(cycle, country_id, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, TermTermType
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -58,5 +60,13 @@ def _run(cycle: dict, country_id: str, N_total: float):
|
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
def run(cycle: dict):
|
|
61
|
-
|
|
63
|
+
default_should_run, country_id, N_total, *args = _should_run(cycle, TERM_ID, TIER)
|
|
64
|
+
term_type_complete = _is_term_type_complete(cycle, TermTermType.EXCRETA)
|
|
65
|
+
|
|
66
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
67
|
+
term_type_excreta_complete=term_type_complete)
|
|
68
|
+
|
|
69
|
+
should_run = all([default_should_run, term_type_complete])
|
|
70
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
71
|
+
|
|
62
72
|
return _run(cycle, country_id, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -61,5 +63,13 @@ def _run(cycle: dict, country_id: str, N_total: float):
|
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
def run(cycle: dict):
|
|
64
|
-
|
|
66
|
+
default_should_run, country_id, N_total, *args = _should_run(cycle, TERM_ID, TIER)
|
|
67
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
68
|
+
|
|
69
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
70
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
71
|
+
|
|
72
|
+
should_run = all([default_should_run, term_type_complete])
|
|
73
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
74
|
+
|
|
65
75
|
return _run(cycle, country_id, N_total) if should_run else []
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
3
4
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
5
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
4
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
7
|
from .noxToAirSoilFlux import _should_run, _get_value
|
|
6
8
|
from . import MODEL
|
|
@@ -61,5 +63,13 @@ def _run(cycle: dict, country_id: str, N_total: float):
|
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
def run(cycle: dict):
|
|
64
|
-
|
|
66
|
+
default_should_run, country_id, N_total, *args = _should_run(cycle, TERM_ID, TIER)
|
|
67
|
+
term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
68
|
+
|
|
69
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
70
|
+
term_type_fertiliser_complete=term_type_complete)
|
|
71
|
+
|
|
72
|
+
should_run = all([default_should_run, term_type_complete])
|
|
73
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
74
|
+
|
|
65
75
|
return _run(cycle, country_id, N_total) if should_run else []
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import calendar
|
|
1
2
|
from calendar import monthrange
|
|
2
3
|
from collections import defaultdict
|
|
3
4
|
from collections.abc import Iterable
|
|
4
|
-
from datetime import datetime
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
5
8
|
from dateutil.relativedelta import relativedelta
|
|
6
9
|
from enum import Enum
|
|
7
10
|
from functools import reduce
|
|
8
|
-
from statistics import mode, mean
|
|
9
11
|
from typing import (
|
|
10
12
|
Any,
|
|
11
13
|
List,
|
|
@@ -24,9 +26,10 @@ from hestia_earth.utils.tools import (
|
|
|
24
26
|
safe_parse_float,
|
|
25
27
|
non_empty_list
|
|
26
28
|
)
|
|
29
|
+
from hestia_earth.utils.blank_node import ArrayTreatment, get_node_value
|
|
27
30
|
|
|
28
31
|
from ..log import debugValues, log_as_table
|
|
29
|
-
from . import is_from_model, _filter_list_term_unit, is_iterable
|
|
32
|
+
from . import is_from_model, _filter_list_term_unit, is_iterable, _omit
|
|
30
33
|
from .constant import Units
|
|
31
34
|
from .property import get_node_property, get_node_property_value
|
|
32
35
|
from .lookup import (
|
|
@@ -46,7 +49,9 @@ def group_by_keys(group_keys: list = ['term']):
|
|
|
46
49
|
return run
|
|
47
50
|
|
|
48
51
|
|
|
49
|
-
def _module_term_id(term_id: str, module):
|
|
52
|
+
def _module_term_id(term_id: str, module):
|
|
53
|
+
term_id_str = term_id.split('.')[-1] if '.' in term_id else term_id
|
|
54
|
+
return getattr(module, 'TERM_ID', term_id_str).split(',')[0]
|
|
50
55
|
|
|
51
56
|
|
|
52
57
|
def _run_model_required(model: str, term: dict, data: dict):
|
|
@@ -342,111 +347,6 @@ def convert_to_carbon(node: dict, model: str, term_id: str, blank_nodes: list, *
|
|
|
342
347
|
]) if len(missing_carbon_property) == 0 else None
|
|
343
348
|
|
|
344
349
|
|
|
345
|
-
class ArrayTreatment(Enum):
|
|
346
|
-
"""
|
|
347
|
-
Enum representing different treatments for arrays of values.
|
|
348
|
-
"""
|
|
349
|
-
MEAN = 'mean'
|
|
350
|
-
MODE = 'mode'
|
|
351
|
-
SUM = 'sum'
|
|
352
|
-
FIRST = 'first'
|
|
353
|
-
LAST = 'last'
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
def _should_run_array_treatment(value):
|
|
357
|
-
return isinstance(value, Iterable) and len(value) > 0
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
DEFAULT_ARRAY_TREATMENT = ArrayTreatment.MEAN
|
|
361
|
-
ARRAY_TREATMENT_TO_REDUCER = {
|
|
362
|
-
ArrayTreatment.MEAN: lambda value: mean(value) if _should_run_array_treatment(value) else 0,
|
|
363
|
-
ArrayTreatment.MODE: lambda value: mode(value) if _should_run_array_treatment(value) else 0,
|
|
364
|
-
ArrayTreatment.SUM: lambda value: sum(value) if _should_run_array_treatment(value) else 0,
|
|
365
|
-
ArrayTreatment.FIRST: lambda value: value[0] if _should_run_array_treatment(value) else 0,
|
|
366
|
-
ArrayTreatment.LAST: lambda value: value[-1] if _should_run_array_treatment(value) else 0
|
|
367
|
-
}
|
|
368
|
-
"""
|
|
369
|
-
A dictionary mapping ArrayTreatment enums to corresponding reducer functions.
|
|
370
|
-
"""
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
def _retrieve_array_treatment(
|
|
374
|
-
node: dict,
|
|
375
|
-
is_larger_unit: bool = False,
|
|
376
|
-
default: ArrayTreatment = ArrayTreatment.FIRST
|
|
377
|
-
) -> ArrayTreatment:
|
|
378
|
-
"""
|
|
379
|
-
Retrieves the array treatment for a given node.
|
|
380
|
-
|
|
381
|
-
Array treatments are used to reduce an array's list of values into
|
|
382
|
-
a single value. The array treatment is retrieved from a lookup on
|
|
383
|
-
the node's term.
|
|
384
|
-
|
|
385
|
-
Parameters
|
|
386
|
-
----------
|
|
387
|
-
node : dict
|
|
388
|
-
The dictionary representing the node.
|
|
389
|
-
is_larger_unit : bool, optional
|
|
390
|
-
Flag indicating whether to use the larger unit lookup, by default `False`.
|
|
391
|
-
default : ArrayTreatment, optional
|
|
392
|
-
Default value to return if the lookup fails, by default `ArrayTreatment.FIRST`.
|
|
393
|
-
|
|
394
|
-
Returns
|
|
395
|
-
-------
|
|
396
|
-
ArrayTreatment
|
|
397
|
-
The retrieved array treatment.
|
|
398
|
-
|
|
399
|
-
"""
|
|
400
|
-
ARRAY_TREATMENT_LOOKUPS = [
|
|
401
|
-
'arrayTreatmentLargerUnitOfTime',
|
|
402
|
-
'arrayTreatment'
|
|
403
|
-
]
|
|
404
|
-
lookup = ARRAY_TREATMENT_LOOKUPS[0] if is_larger_unit else ARRAY_TREATMENT_LOOKUPS[1]
|
|
405
|
-
|
|
406
|
-
term = node.get('term', {})
|
|
407
|
-
lookup_value = get_lookup_value(term, lookup, skip_debug=True)
|
|
408
|
-
|
|
409
|
-
return next(
|
|
410
|
-
(treatment for treatment in ArrayTreatment if treatment.value == lookup_value),
|
|
411
|
-
default
|
|
412
|
-
)
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
def get_node_value(
|
|
416
|
-
node: dict,
|
|
417
|
-
is_larger_unit: bool = False,
|
|
418
|
-
array_treatment: Optional[ArrayTreatment] = None,
|
|
419
|
-
default: Any = 0
|
|
420
|
-
) -> Union[float, bool]:
|
|
421
|
-
"""
|
|
422
|
-
Get the value from the dictionary representing the node,
|
|
423
|
-
applying optional array treatment if the value is a list.
|
|
424
|
-
|
|
425
|
-
Parameters
|
|
426
|
-
----------
|
|
427
|
-
node : dict
|
|
428
|
-
The dictionary representing the node.
|
|
429
|
-
is_larger_unit : bool, optional
|
|
430
|
-
A flag indicating whether the unit of time is larger, by default `False`.
|
|
431
|
-
array_treatment : ArrayTreatment, optional
|
|
432
|
-
An optional override for the treatment to be applied to an array value, if `None` the array treatment in the
|
|
433
|
-
node's term's lookup is used (which defaults to `FIRST` if no array treatment is specified), by default `None`.
|
|
434
|
-
|
|
435
|
-
Returns
|
|
436
|
-
-------
|
|
437
|
-
float | bool
|
|
438
|
-
The extracted value from the node.
|
|
439
|
-
|
|
440
|
-
"""
|
|
441
|
-
value = node.get("value", 0)
|
|
442
|
-
|
|
443
|
-
reducer = ARRAY_TREATMENT_TO_REDUCER[(
|
|
444
|
-
array_treatment or _retrieve_array_treatment(node, is_larger_unit=is_larger_unit)
|
|
445
|
-
)] if isinstance(value, list) and len(value) > 0 else None
|
|
446
|
-
|
|
447
|
-
return reducer(value) if reducer else value if isinstance(value, bool) else value or default
|
|
448
|
-
|
|
449
|
-
|
|
450
350
|
def _convert_to_set(
|
|
451
351
|
variable: Union[Iterable[Any], Any]
|
|
452
352
|
) -> set:
|
|
@@ -560,7 +460,7 @@ def cumulative_nodes_match(
|
|
|
560
460
|
"""
|
|
561
461
|
values = [
|
|
562
462
|
get_node_value(
|
|
563
|
-
node, is_larger_unit, array_treatment
|
|
463
|
+
node, 'value', is_larger_unit, array_treatment
|
|
564
464
|
) or default_node_value for node in nodes if function(node)
|
|
565
465
|
]
|
|
566
466
|
|
|
@@ -1274,3 +1174,99 @@ def get_inputs_from_properties(input: dict, term_types: Union[TermTermType, List
|
|
|
1274
1174
|
} for p in (properties or []) if all([p.get('key'), p.get('value')])
|
|
1275
1175
|
]) if input_value > 0 else []
|
|
1276
1176
|
return filter_list_term_type(inputs, term_types)
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
def _get_condensed_nodes(nodes: list) -> tuple[list, bool]:
|
|
1180
|
+
"""Only considers nodes which already match on non-date criteria."""
|
|
1181
|
+
CONDENSABLE_UNITS = [Units.BOOLEAN.value, Units.PERCENTAGE_AREA.value]
|
|
1182
|
+
condensed_nodes = []
|
|
1183
|
+
matched_uuids = set()
|
|
1184
|
+
nodes_by_start_date = {_full_date_str(date_str=n["startDate"], is_end=True): n for n in nodes if "startDate" in n}
|
|
1185
|
+
if len(nodes_by_start_date) != len(nodes):
|
|
1186
|
+
return nodes, False
|
|
1187
|
+
|
|
1188
|
+
for node in nodes:
|
|
1189
|
+
search_date = _offset_date(date_str=node.get("endDate", ""))
|
|
1190
|
+
if node["uuid"] in matched_uuids:
|
|
1191
|
+
continue
|
|
1192
|
+
if (search_date in nodes_by_start_date and nodes_by_start_date[search_date]["uuid"] not in matched_uuids
|
|
1193
|
+
and node.get("term", {}).get("units") in CONDENSABLE_UNITS):
|
|
1194
|
+
new_node = node.copy()
|
|
1195
|
+
new_node["endDate"] = nodes_by_start_date[search_date]["endDate"]
|
|
1196
|
+
condensed_nodes.append(new_node)
|
|
1197
|
+
matched_uuids.add(nodes_by_start_date[search_date]["uuid"])
|
|
1198
|
+
elif node["uuid"] not in matched_uuids:
|
|
1199
|
+
condensed_nodes.append(node)
|
|
1200
|
+
|
|
1201
|
+
return condensed_nodes, len(matched_uuids) > 0
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
def condense_nodes(nodes: list) -> list:
|
|
1205
|
+
grouped_nodes = _group_nodes_by_term_and_value(nodes)
|
|
1206
|
+
condensed_nodes = dict()
|
|
1207
|
+
any_changes_made = False
|
|
1208
|
+
|
|
1209
|
+
for key, node_group in grouped_nodes.items():
|
|
1210
|
+
condensed_nodes[key] = node_group
|
|
1211
|
+
while len(condensed_nodes[key]) > 1:
|
|
1212
|
+
condensed_nodes[key], changes_made = _get_condensed_nodes(condensed_nodes[key])
|
|
1213
|
+
if not changes_made:
|
|
1214
|
+
break
|
|
1215
|
+
any_changes_made = True
|
|
1216
|
+
|
|
1217
|
+
if not any_changes_made:
|
|
1218
|
+
return [_omit(values=n, keys=["uuid"]) for n in nodes]
|
|
1219
|
+
|
|
1220
|
+
return sorted(
|
|
1221
|
+
flatten([_omit(values=n, keys=["uuid"]) for nodes in condensed_nodes.values() for n in nodes]),
|
|
1222
|
+
key=lambda x: x["startDate"]
|
|
1223
|
+
)
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
DATE_FORMAT = "%Y-%m-%d"
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
def _variable_length_str_to_date(date_str: str, is_end: bool) -> datetime:
|
|
1230
|
+
"""Converts to date, adding start or end of year to YYYY strings as indicated by is_end."""
|
|
1231
|
+
return datetime.strptime(_full_date_str(date_str, is_end=is_end), DATE_FORMAT)
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
def _full_date_str(date_str: str, is_end: bool) -> str:
|
|
1235
|
+
suffix = ""
|
|
1236
|
+
if len(date_str) == 4:
|
|
1237
|
+
# Format YYYY
|
|
1238
|
+
suffix = "-12-31" if is_end else "-01-01"
|
|
1239
|
+
elif len(date_str) == 7:
|
|
1240
|
+
# Format YYYY-MM
|
|
1241
|
+
suffix = f"-{calendar.monthrange(int(date_str[:4]), int(date_str[5:7]))[1]}" if is_end else "-01"
|
|
1242
|
+
|
|
1243
|
+
return date_str + suffix
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
def _with_full_dates(node: dict) -> dict:
|
|
1247
|
+
output_node = node.copy()
|
|
1248
|
+
if "startDate" in output_node:
|
|
1249
|
+
output_node["startDate"] = _full_date_str(output_node["startDate"], is_end=False)
|
|
1250
|
+
if "endDate" in output_node:
|
|
1251
|
+
output_node["endDate"] = _full_date_str(output_node["endDate"], is_end=True)
|
|
1252
|
+
|
|
1253
|
+
return output_node
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
def _offset_date(date_str: str, days: int = 1, is_end: bool = True) -> str:
|
|
1257
|
+
return (
|
|
1258
|
+
_variable_length_str_to_date(date_str=date_str, is_end=is_end) + timedelta(days=days)
|
|
1259
|
+
).strftime(DATE_FORMAT)
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
def _group_nodes_by_term_and_value(nodes: list) -> dict:
|
|
1263
|
+
grouped_nodes = defaultdict(list)
|
|
1264
|
+
|
|
1265
|
+
for node in nodes:
|
|
1266
|
+
term_id = node.get("term", {}).get("@id", "")
|
|
1267
|
+
value = "-".join([str(v) for v in node.get("value")]) if isinstance(node.get("value"), list) \
|
|
1268
|
+
else node.get("value")
|
|
1269
|
+
node["uuid"] = uuid4()
|
|
1270
|
+
grouped_nodes[(term_id, value)].append(_with_full_dates(node))
|
|
1271
|
+
|
|
1272
|
+
return grouped_nodes
|
|
@@ -3,6 +3,7 @@ from hestia_earth.utils.tools import list_sum
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class Units(Enum):
|
|
6
|
+
BOOLEAN = 'boolean'
|
|
6
7
|
HEAD = 'head'
|
|
7
8
|
NUMBER = 'number'
|
|
8
9
|
KG = 'kg'
|
|
@@ -31,6 +32,7 @@ class Units(Enum):
|
|
|
31
32
|
KG_COLD_CARCASS_WEIGHT = 'kg cold carcass weight'
|
|
32
33
|
KG_COLD_DRESSED_CARCASS_WEIGHT = 'kg cold dressed carcass weight'
|
|
33
34
|
KG_READY_TO_COOK_WEIGHT = 'kg ready-to-cook weight'
|
|
35
|
+
PERCENTAGE_AREA = '% area'
|
|
34
36
|
TO_C = '-C'
|
|
35
37
|
TO_N = '-N'
|
|
36
38
|
|
|
@@ -76,6 +76,17 @@ _ALLOW_ALL = 'all'
|
|
|
76
76
|
def _is_site(site: dict): return site.get('@type', site.get('type')) == SchemaType.SITE.value
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
def _get_sites(node: dict):
|
|
80
|
+
site = node.get('site', node.get('cycle', {}).get('site'))
|
|
81
|
+
other_sites = node.get('otherSites', node.get('cycle', {}).get('otherSites', []))
|
|
82
|
+
return non_empty_list([site] + other_sites)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _get_site_types(node: dict):
|
|
86
|
+
sites = [node] if _is_site(node) else _get_sites(node)
|
|
87
|
+
return non_empty_list([site.get('siteType') for site in sites])
|
|
88
|
+
|
|
89
|
+
|
|
79
90
|
def _model_lookup_values(model: str, term: dict, restriction: str):
|
|
80
91
|
lookup = download_lookup(f"{term.get('termType')}-model-{restriction}.csv")
|
|
81
92
|
values = get_table_value(lookup, 'termid', term.get('@id'), column_name(model))
|
|
@@ -83,10 +94,11 @@ def _model_lookup_values(model: str, term: dict, restriction: str):
|
|
|
83
94
|
|
|
84
95
|
|
|
85
96
|
def is_model_siteType_allowed(model: str, term: dict, data: dict):
|
|
86
|
-
|
|
87
|
-
site_type = site.get('siteType')
|
|
97
|
+
site_types = _get_site_types(data)
|
|
88
98
|
allowed_values = _model_lookup_values(model, term, 'siteTypesAllowed')
|
|
89
|
-
return True if _ALLOW_ALL in allowed_values or not
|
|
99
|
+
return True if _ALLOW_ALL in allowed_values or not site_types else any([
|
|
100
|
+
(site_type in allowed_values) for site_type in site_types
|
|
101
|
+
])
|
|
90
102
|
|
|
91
103
|
|
|
92
104
|
def _lookup_values(term: dict, column: str):
|
|
@@ -96,10 +108,11 @@ def _lookup_values(term: dict, column: str):
|
|
|
96
108
|
|
|
97
109
|
|
|
98
110
|
def is_siteType_allowed(data: dict, term: dict):
|
|
99
|
-
|
|
100
|
-
site_type = site.get('siteType')
|
|
111
|
+
site_types = _get_site_types(data)
|
|
101
112
|
allowed_values = _lookup_values(term, 'siteTypesAllowed')
|
|
102
|
-
return True if _ALLOW_ALL in allowed_values or not
|
|
113
|
+
return True if _ALLOW_ALL in allowed_values or not site_types else any([
|
|
114
|
+
(site_type in allowed_values) for site_type in site_types
|
|
115
|
+
])
|
|
103
116
|
|
|
104
117
|
|
|
105
118
|
def is_product_termType_allowed(data: dict, term: dict):
|