hestia-earth-models 0.72.2__py3-none-any.whl → 0.73.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.
- hestia_earth/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +1 -1
- hestia_earth/models/akagiEtAl2011/ch4ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/nh3ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/noxToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/pm25ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/so2ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/utils.py +45 -0
- hestia_earth/models/aware/scarcityWeightedWaterUse.py +2 -2
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/utils.py +1 -1
- hestia_earth/models/config/Cycle.json +48 -7
- hestia_earth/models/config/ImpactAssessment.json +22 -0
- hestia_earth/models/cycle/completeness/soilAmendment.py +1 -1
- hestia_earth/models/cycle/product/economicValueShare.py +3 -1
- hestia_earth/models/cycle/product/price.py +35 -10
- hestia_earth/models/cycle/product/revenue.py +5 -2
- hestia_earth/models/dammgen2009/noxToAirExcreta.py +14 -18
- hestia_earth/models/ecoinventV3/__init__.py +11 -6
- hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
- hestia_earth/models/emepEea2019/utils.py +2 -1
- hestia_earth/models/faostat2018/liveweightPerHead.py +1 -1
- hestia_earth/models/faostat2018/product/price.py +2 -2
- hestia_earth/models/faostat2018/seed.py +3 -2
- hestia_earth/models/faostat2018/utils.py +6 -5
- hestia_earth/models/geospatialDatabase/altitude.py +2 -1
- hestia_earth/models/geospatialDatabase/drainageClass.py +2 -1
- hestia_earth/models/geospatialDatabase/organicCarbonPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/totalNitrogenPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/totalPhosphorusPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/utils.py +1 -1
- hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +1 -1
- hestia_earth/models/hestia/brackishWater.py +1 -1
- hestia_earth/models/hestia/default_emissions.py +105 -0
- hestia_earth/models/hestia/default_resourceUse.py +110 -0
- hestia_earth/models/hestia/freshWater.py +1 -1
- hestia_earth/models/hestia/inorganicFertiliser.py +12 -12
- hestia_earth/models/hestia/landCover.py +7 -5
- hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +3 -0
- hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +3 -0
- hestia_earth/models/hestia/liveAnimal.py +1 -1
- hestia_earth/models/hestia/management.py +1 -1
- hestia_earth/models/hestia/netPrimaryProduction.py +1 -1
- hestia_earth/models/hestia/organicCarbonPerHa.py +2 -2
- hestia_earth/models/hestia/salineWater.py +1 -1
- hestia_earth/models/hestia/seed_emissions.py +34 -20
- hestia_earth/models/hestia/totalNitrogenPerKgSoil.py +1 -1
- hestia_earth/models/hestia/waterSalinity.py +2 -1
- hestia_earth/models/ipcc2006/aboveGroundCropResidueRemoved.py +2 -2
- hestia_earth/models/ipcc2006/aboveGroundCropResidueTotal.py +10 -6
- hestia_earth/models/ipcc2006/belowGroundCropResidue.py +12 -8
- hestia_earth/models/ipcc2019/animal/utils.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
- hestia_earth/models/ipcc2019/carbonContent.py +1 -1
- hestia_earth/models/ipcc2019/ch4ToAirAquacultureSystems.py +17 -9
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +6 -6
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +4 -2
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +1 -1
- hestia_earth/models/ipcc2019/croppingDuration.py +4 -2
- hestia_earth/models/ipcc2019/ligninContent.py +1 -1
- hestia_earth/models/{akagiEtAl2011AndIpcc2006 → ipcc2019}/n2OToAirCropResidueBurningDirect.py +8 -4
- hestia_earth/models/ipcc2019/nitrogenContent.py +1 -1
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +6 -2
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +13 -12
- hestia_earth/models/ipcc2019/utils.py +6 -2
- hestia_earth/models/koble2014/residueBurnt.py +6 -3
- hestia_earth/models/koble2014/residueRemoved.py +1 -1
- hestia_earth/models/mocking/search-results.json +1577 -1573
- hestia_earth/models/pooreNemecek2018/aboveGroundCropResidueTotal.py +1 -1
- hestia_earth/models/pooreNemecek2018/belowGroundCropResidue.py +1 -1
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +1 -1
- hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +1 -1
- hestia_earth/models/pooreNemecek2018/longFallowDuration.py +1 -1
- hestia_earth/models/pooreNemecek2018/nurseryDensity.py +1 -1
- hestia_earth/models/pooreNemecek2018/nurseryDuration.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationDensity.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationLifespan.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationProductiveLifespan.py +3 -1
- hestia_earth/models/pooreNemecek2018/saplingsDepreciatedAmountPerCycle.py +1 -1
- hestia_earth/models/resourceUseNotRelevant/__init__.py +65 -0
- hestia_earth/models/schererPfister2015/nErosionSoilFlux.py +5 -3
- hestia_earth/models/schererPfister2015/pErosionSoilFlux.py +5 -3
- hestia_earth/models/schererPfister2015/utils.py +5 -4
- hestia_earth/models/stehfestBouwman2006/n2OToAirSoilFlux_utils.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirSoilFlux_utils.py +3 -3
- hestia_earth/models/utils/background_emissions.py +14 -10
- hestia_earth/models/utils/blank_node.py +6 -4
- hestia_earth/models/utils/crop.py +1 -1
- hestia_earth/models/utils/cropResidue.py +16 -0
- hestia_earth/models/utils/cycle.py +1 -1
- hestia_earth/models/utils/ecoClimateZone.py +2 -2
- hestia_earth/models/utils/excretaManagement.py +1 -1
- hestia_earth/models/utils/feedipedia.py +3 -3
- hestia_earth/models/utils/fertiliser.py +7 -1
- hestia_earth/models/utils/inorganicFertiliser.py +2 -2
- hestia_earth/models/utils/input.py +34 -1
- hestia_earth/models/utils/liveAnimal.py +2 -2
- hestia_earth/models/utils/lookup.py +1 -1
- hestia_earth/models/utils/measurement.py +5 -4
- hestia_earth/models/utils/productivity.py +1 -1
- hestia_earth/models/utils/property.py +4 -2
- hestia_earth/models/utils/site.py +2 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/RECORD +124 -113
- tests/models/akagiEtAl2011/test_ch4ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_nh3ToAirCropResidueBurning.py +33 -0
- tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/test_noxToAirCropResidueBurning.py +5 -17
- tests/models/akagiEtAl2011/test_pm25ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_so2ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_utils.py +18 -0
- tests/models/cycle/product/test_price.py +1 -11
- tests/models/dammgen2009/test_noxToAirExcreta.py +30 -10
- tests/models/geospatialDatabase/test_utils.py +2 -1
- tests/models/hestia/test_default_emissions.py +25 -0
- tests/models/hestia/test_default_resourceUse.py +26 -0
- tests/models/hestia/test_landCover.py +2 -2
- tests/models/ipcc2019/test_ch4ToAirAquacultureSystems.py +2 -2
- tests/models/{akagiEtAl2011AndIpcc2006/test_nh3ToAirCropResidueBurning.py → ipcc2019/test_n2OToAirCropResidueBurningDirect.py} +2 -2
- tests/models/test_resourceUseNotRelevant.py +27 -0
- tests/models/{akagiEtAl2011AndIpcc2006/test_utils.py → utils/test_cropResidue.py} +6 -6
- hestia_earth/models/akagiEtAl2011AndIpcc2006/ch4ToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/nh3ToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/noxToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/utils.py +0 -15
- tests/models/akagiEtAl2011AndIpcc2006/test_ch4ToAirCropResidueBurning.py +0 -45
- tests/models/akagiEtAl2011AndIpcc2006/test_n2OToAirCropResidueBurningDirect.py +0 -46
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/top_level.txt +0 -0
- /tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +0 -0
@@ -65,7 +65,7 @@ def _lookup_data(
|
|
65
65
|
def get_data(country_id):
|
66
66
|
data = get_region_lookup_value(lookup_name, country_id, grouping, model=MODEL, term=term_id, key=MODEL_KEY)
|
67
67
|
price = extract_grouped_data(data, str(year)) or extract_grouped_data(data, 'Average_price_per_tonne')
|
68
|
-
return safe_parse_float(price, None)
|
68
|
+
return safe_parse_float(price, default=None)
|
69
69
|
|
70
70
|
# try get country data first, falls back to region data
|
71
71
|
country_id = country.get('@id')
|
@@ -141,7 +141,7 @@ def _run_by_country(cycle: dict, product: dict, country: dict, year: int = None)
|
|
141
141
|
|
142
142
|
# if units is number instead of kg, need to convert to number first
|
143
143
|
conversion_to_number = safe_parse_float(
|
144
|
-
get_region_lookup_value(LOOKUP_UNITS_NUMBER.get(term_type), country.get('@id'), grouping), 1
|
144
|
+
get_region_lookup_value(LOOKUP_UNITS_NUMBER.get(term_type), country.get('@id'), grouping), default=1
|
145
145
|
) if term_units == Units.NUMBER.value else 1
|
146
146
|
|
147
147
|
logRequirements(cycle, model=MODEL, term=term_id, key=MODEL_KEY, by='country',
|
@@ -43,8 +43,9 @@ def _input(value: float, sd: float):
|
|
43
43
|
def _run_product(product: dict):
|
44
44
|
term = product.get('term', {})
|
45
45
|
product_value = list_sum(product.get('value', []))
|
46
|
-
value = safe_parse_float(
|
47
|
-
|
46
|
+
value = safe_parse_float(
|
47
|
+
get_lookup_value(term, LOOKUPS['crop'][0], model=MODEL, term=TERM_ID), default=0) * product_value
|
48
|
+
sd = safe_parse_float(get_lookup_value(term, LOOKUPS['crop'][1], model=MODEL, term=TERM_ID), default=0)
|
48
49
|
return value, sd
|
49
50
|
|
50
51
|
|
@@ -34,10 +34,10 @@ def product_equivalent_value(product: dict, year: int, country: str):
|
|
34
34
|
return None
|
35
35
|
|
36
36
|
quantity_values = get_region_lookup_value(f"{LOOKUP_PREFIX}-productionQuantity.csv", country, grouping)
|
37
|
-
quantity = safe_parse_float(extract_grouped_data_closest_date(quantity_values, year))
|
37
|
+
quantity = safe_parse_float(extract_grouped_data_closest_date(quantity_values, year), default=0)
|
38
38
|
|
39
39
|
head_values = get_region_lookup_value(f"{LOOKUP_PREFIX}-head.csv", country, grouping)
|
40
|
-
head = safe_parse_float(extract_grouped_data_closest_date(head_values, year))
|
40
|
+
head = safe_parse_float(extract_grouped_data_closest_date(head_values, year), default=0)
|
41
41
|
|
42
42
|
# quantity is in Tonnes
|
43
43
|
value = quantity * 1000 / head if head > 0 else 0
|
@@ -58,7 +58,7 @@ def product_equivalent_value(product: dict, year: int, country: str):
|
|
58
58
|
def _split_delta(table_value: str, start_year: int, end_year: int):
|
59
59
|
start_value = extract_grouped_data_closest_date(table_value, start_year)
|
60
60
|
end_value = extract_grouped_data_closest_date(table_value, end_year)
|
61
|
-
return safe_parse_float(end_value) - safe_parse_float(start_value) if all([
|
61
|
+
return safe_parse_float(end_value, default=None) - safe_parse_float(start_value, default=None) if all([
|
62
62
|
start_value is not None, end_value is not None
|
63
63
|
]) else None
|
64
64
|
|
@@ -69,7 +69,8 @@ def get_sum_of_columns(country: str, year: int, columns_list: list) -> float:
|
|
69
69
|
extract_grouped_data_closest_date(
|
70
70
|
data=get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, col, model=MODEL),
|
71
71
|
year=year
|
72
|
-
)
|
72
|
+
),
|
73
|
+
default=0
|
73
74
|
) for col in columns_list]
|
74
75
|
)
|
75
76
|
|
@@ -128,7 +129,7 @@ def get_change_in_harvested_area_for_crop(country_id: str, crop_name: str, start
|
|
128
129
|
lookup_name = 'region-crop-cropGroupingFaostatProduction-areaHarvested.csv'
|
129
130
|
value = get_region_lookup_value(lookup_name, country_id, crop_name)
|
130
131
|
return safe_parse_float(
|
131
|
-
extract_grouped_data_closest_date(value, start_year)
|
132
|
+
extract_grouped_data_closest_date(value, start_year), default=0
|
132
133
|
) if end_year == 0 or end_year == start_year else _split_delta(value, start_year, end_year)
|
133
134
|
|
134
135
|
|
@@ -42,7 +42,8 @@ def _measurement(site: dict, value: float):
|
|
42
42
|
|
43
43
|
def _run(site: dict):
|
44
44
|
value = download(TERM_ID, site, EE_PARAMS)
|
45
|
-
|
45
|
+
value = safe_parse_float(value, default=None)
|
46
|
+
return [_measurement(site, value)] if value is not None else []
|
46
47
|
|
47
48
|
|
48
49
|
def _should_run(site: dict):
|
@@ -40,7 +40,8 @@ def _measurement(site: dict, value: float):
|
|
40
40
|
|
41
41
|
def _run(site: dict):
|
42
42
|
value = download(TERM_ID, site, EE_PARAMS)
|
43
|
-
|
43
|
+
value = safe_parse_float(value, default=None)
|
44
|
+
return [_measurement(site, value)] if value is not None else []
|
44
45
|
|
45
46
|
|
46
47
|
def _should_run(site: dict):
|
@@ -69,8 +69,9 @@ def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
69
69
|
|
70
70
|
def _run_depths(site: dict, params: dict):
|
71
71
|
value = download(TERM_ID, site, params)
|
72
|
+
value = safe_parse_float(value, default=None)
|
72
73
|
return None if value is None else (
|
73
|
-
_measurement(site,
|
74
|
+
_measurement(site, value * 10, params.get('depthUpper'), params.get('depthLower'))
|
74
75
|
)
|
75
76
|
|
76
77
|
|
@@ -69,8 +69,9 @@ def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
69
69
|
|
70
70
|
def _run_depths(site: dict, params: dict):
|
71
71
|
value = download(TERM_ID, site, params)
|
72
|
+
value = safe_parse_float(value, default=None)
|
72
73
|
return None if value is None else (
|
73
|
-
_measurement(site,
|
74
|
+
_measurement(site, value, params.get('depthUpper'), params.get('depthLower'))
|
74
75
|
)
|
75
76
|
|
76
77
|
|
@@ -44,7 +44,8 @@ def _measurement(site: dict, value: float):
|
|
44
44
|
|
45
45
|
def _run(site: dict):
|
46
46
|
value = download(TERM_ID, site, EE_PARAMS)
|
47
|
-
|
47
|
+
value = safe_parse_float(value, default=None)
|
48
|
+
return [_measurement(site, value)] if value is not None else []
|
48
49
|
|
49
50
|
|
50
51
|
def _should_run(site: dict):
|
@@ -111,7 +111,7 @@ def _is_below_max_size(term: str, site: dict) -> bool:
|
|
111
111
|
current_size = _cached_value(site, CACHE_AREA_SIZE) or get_area_size(site)
|
112
112
|
if current_size is not None:
|
113
113
|
logRequirements(site, model=MODEL, term=term,
|
114
|
-
current_size=
|
114
|
+
current_size=round(float(current_size), 5),
|
115
115
|
max_area_size=MAX_AREA_SIZE)
|
116
116
|
return current_size <= MAX_AREA_SIZE
|
117
117
|
return True
|
@@ -60,7 +60,7 @@ def _get_value(cycle: dict, term: dict, irrigation_ids: list):
|
|
60
60
|
else:
|
61
61
|
column = 'Rooting_depth_average_m'
|
62
62
|
|
63
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, column), None)
|
63
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, column), default=None)
|
64
64
|
|
65
65
|
|
66
66
|
def _should_run_product(cycle: dict):
|
@@ -34,7 +34,7 @@ def _should_run(site: dict):
|
|
34
34
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
35
35
|
waterSalinity=waterSalinity)
|
36
36
|
|
37
|
-
should_run = all([500 <= waterSalinity <= 18000])
|
37
|
+
should_run = all([500 <= (waterSalinity or 0) <= 18000])
|
38
38
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
39
39
|
return should_run
|
40
40
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier
|
2
|
+
from hestia_earth.utils.tools import flatten, safe_parse_float
|
3
|
+
from hestia_earth.utils.emission import cycle_emissions_in_system_boundary
|
4
|
+
|
5
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
6
|
+
from hestia_earth.models.utils import _omit
|
7
|
+
from hestia_earth.models.utils.emission import _new_emission
|
8
|
+
from hestia_earth.models.utils.background_emissions import no_gap_filled_background_emissions
|
9
|
+
from hestia_earth.models.utils.blank_node import get_lookup_value
|
10
|
+
from hestia_earth.models.utils.input import unique_background_inputs
|
11
|
+
from . import MODEL
|
12
|
+
|
13
|
+
REQUIREMENTS = {
|
14
|
+
"Cycle": {
|
15
|
+
"inputs": [{
|
16
|
+
"@type": "Input",
|
17
|
+
"value": "> 0",
|
18
|
+
"none": {
|
19
|
+
"impactAssessment": {"@type": "ImpactAssessment"},
|
20
|
+
"fromCycle": "True",
|
21
|
+
"producedInCycle": "True"
|
22
|
+
}
|
23
|
+
}]
|
24
|
+
}
|
25
|
+
}
|
26
|
+
RETURNS = {
|
27
|
+
"Emission": [{
|
28
|
+
"value": "",
|
29
|
+
"inputs": "",
|
30
|
+
"methodTier": "background"
|
31
|
+
}]
|
32
|
+
}
|
33
|
+
LOOKUPS = {
|
34
|
+
"organicFertiliser": "backgroundEmissionsResourceUseDefaultValue"
|
35
|
+
}
|
36
|
+
MODEL_KEY = 'default_emissions'
|
37
|
+
TIER = EmissionMethodTier.BACKGROUND.value
|
38
|
+
|
39
|
+
|
40
|
+
def _emission(term_id: str, value: float, input: dict):
|
41
|
+
emission = _new_emission(term_id, MODEL)
|
42
|
+
emission['value'] = [value]
|
43
|
+
emission['inputs'] = [input]
|
44
|
+
emission['methodTier'] = TIER
|
45
|
+
return emission
|
46
|
+
|
47
|
+
|
48
|
+
def _default_value(input: dict):
|
49
|
+
return safe_parse_float(get_lookup_value(input.get('term', {}), LOOKUPS['organicFertiliser']), default=None)
|
50
|
+
|
51
|
+
|
52
|
+
def _run_input(cycle: dict):
|
53
|
+
required_emission_term_ids = [
|
54
|
+
id for id in cycle_emissions_in_system_boundary(cycle)
|
55
|
+
if id.endswith('InputsProduction')
|
56
|
+
]
|
57
|
+
|
58
|
+
def run(input: dict):
|
59
|
+
input_term = input.get('input').get('term')
|
60
|
+
term_id = input_term.get('@id')
|
61
|
+
value = input.get('default-value-from-lookup')
|
62
|
+
|
63
|
+
for emission_id in required_emission_term_ids:
|
64
|
+
logShouldRun(cycle, MODEL, term_id, True, methodTier=TIER, model_key=MODEL_KEY, emission_id=emission_id)
|
65
|
+
|
66
|
+
return [
|
67
|
+
_emission(term_id, value, input_term) for term_id in required_emission_term_ids
|
68
|
+
]
|
69
|
+
|
70
|
+
return run
|
71
|
+
|
72
|
+
|
73
|
+
def _should_run(cycle: dict):
|
74
|
+
no_gap_filled_background_emissions_func = no_gap_filled_background_emissions(cycle)
|
75
|
+
|
76
|
+
inputs = [
|
77
|
+
input | {
|
78
|
+
'default-value-from-lookup': _default_value(input['input']),
|
79
|
+
'no-gap-filled-background-emissions': no_gap_filled_background_emissions_func(input['input'])
|
80
|
+
}
|
81
|
+
for input in unique_background_inputs(cycle)
|
82
|
+
]
|
83
|
+
valid_inputs = [
|
84
|
+
input for input in inputs
|
85
|
+
if all([
|
86
|
+
input.get('default-value-from-lookup') is not None,
|
87
|
+
input.get('no-gap-filled-background-emissions')
|
88
|
+
])
|
89
|
+
]
|
90
|
+
|
91
|
+
should_run = all([bool(valid_inputs)])
|
92
|
+
|
93
|
+
for input in inputs:
|
94
|
+
term_id = input.get('input').get('term', {}).get('@id')
|
95
|
+
|
96
|
+
logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
97
|
+
**_omit(input, ['input', 'input-value']))
|
98
|
+
logShouldRun(cycle, MODEL, term_id, should_run, methodTier=TIER, model_key=MODEL_KEY)
|
99
|
+
|
100
|
+
return should_run, valid_inputs
|
101
|
+
|
102
|
+
|
103
|
+
def run(cycle: dict):
|
104
|
+
should_run, grouped_inputs = _should_run(cycle)
|
105
|
+
return flatten(map(_run_input(cycle), grouped_inputs)) if should_run else []
|
@@ -0,0 +1,110 @@
|
|
1
|
+
from hestia_earth.schema import IndicatorMethodTier, TermTermType
|
2
|
+
from hestia_earth.utils.tools import flatten, safe_parse_float
|
3
|
+
from hestia_earth.utils.lookup import download_lookup, lookup_term_ids
|
4
|
+
|
5
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
6
|
+
from hestia_earth.models.utils import _omit
|
7
|
+
from hestia_earth.models.utils.indicator import _new_indicator
|
8
|
+
from hestia_earth.models.utils.background_emissions import no_gap_filled_background_emissions
|
9
|
+
from hestia_earth.models.utils.blank_node import get_lookup_value
|
10
|
+
from hestia_earth.models.utils.input import unique_background_inputs
|
11
|
+
from . import MODEL
|
12
|
+
|
13
|
+
REQUIREMENTS = {
|
14
|
+
"ImpactAssessment": {
|
15
|
+
"cycle": {
|
16
|
+
"@type": "Cycle",
|
17
|
+
"inputs": [{
|
18
|
+
"@type": "Input",
|
19
|
+
"value": "> 0",
|
20
|
+
"none": {
|
21
|
+
"impactAssessment": {"@type": "ImpactAssessment"},
|
22
|
+
"fromCycle": "True",
|
23
|
+
"producedInCycle": "True"
|
24
|
+
}
|
25
|
+
}]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
RETURNS = {
|
30
|
+
"Indicator": [{
|
31
|
+
"value": "",
|
32
|
+
"inputs": "",
|
33
|
+
"methodTier": "background"
|
34
|
+
}]
|
35
|
+
}
|
36
|
+
LOOKUPS = {
|
37
|
+
"organicFertiliser": "backgroundEmissionsResourceUseDefaultValue"
|
38
|
+
}
|
39
|
+
MODEL_KEY = 'default_resourceUse'
|
40
|
+
TIER = IndicatorMethodTier.BACKGROUND.value
|
41
|
+
|
42
|
+
|
43
|
+
def _indicator(term_id: str, value: float, input: dict):
|
44
|
+
indicator = _new_indicator(term_id, MODEL)
|
45
|
+
indicator['value'] = value
|
46
|
+
indicator['inputs'] = [input]
|
47
|
+
indicator['methodTier'] = TIER
|
48
|
+
return indicator
|
49
|
+
|
50
|
+
|
51
|
+
def _default_value(input: dict):
|
52
|
+
return safe_parse_float(get_lookup_value(input.get('term', {}), LOOKUPS['organicFertiliser']), default=None)
|
53
|
+
|
54
|
+
|
55
|
+
def _run_input(impact: dict):
|
56
|
+
required_resourceUse_term_ids = [
|
57
|
+
id for id in lookup_term_ids(download_lookup(f"{TermTermType.RESOURCEUSE.value}.csv"))
|
58
|
+
if id.endswith('InputsProduction')
|
59
|
+
]
|
60
|
+
|
61
|
+
def run(input: dict):
|
62
|
+
input_term = input.get('input').get('term')
|
63
|
+
term_id = input_term.get('@id')
|
64
|
+
value = input.get('default-value-from-lookup')
|
65
|
+
|
66
|
+
for emission_id in required_resourceUse_term_ids:
|
67
|
+
logShouldRun(impact, MODEL, term_id, True, methodTier=TIER, model_key=MODEL_KEY, emission_id=emission_id)
|
68
|
+
|
69
|
+
return [
|
70
|
+
_indicator(term_id, value, input_term) for term_id in required_resourceUse_term_ids
|
71
|
+
]
|
72
|
+
|
73
|
+
return run
|
74
|
+
|
75
|
+
|
76
|
+
def _should_run(impact: dict):
|
77
|
+
no_gap_filled_background_emissions_func = no_gap_filled_background_emissions(
|
78
|
+
node=impact, list_key='emissionsResourceUse', term_type=TermTermType.RESOURCEUSE
|
79
|
+
)
|
80
|
+
|
81
|
+
inputs = [
|
82
|
+
input | {
|
83
|
+
'default-value-from-lookup': _default_value(input['input']),
|
84
|
+
'no-gap-filled-background-emissions': no_gap_filled_background_emissions_func(input['input'])
|
85
|
+
}
|
86
|
+
for input in unique_background_inputs(impact.get('cycle', {}))
|
87
|
+
]
|
88
|
+
valid_inputs = [
|
89
|
+
input for input in inputs
|
90
|
+
if all([
|
91
|
+
input.get('default-value-from-lookup') is not None,
|
92
|
+
input.get('no-gap-filled-background-emissions')
|
93
|
+
])
|
94
|
+
]
|
95
|
+
|
96
|
+
should_run = all([bool(valid_inputs)])
|
97
|
+
|
98
|
+
for input in inputs:
|
99
|
+
term_id = input.get('input').get('term', {}).get('@id')
|
100
|
+
|
101
|
+
logRequirements(impact, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
102
|
+
**_omit(input, ['input', 'input-value']))
|
103
|
+
logShouldRun(impact, MODEL, term_id, should_run, methodTier=TIER, model_key=MODEL_KEY)
|
104
|
+
|
105
|
+
return should_run, valid_inputs
|
106
|
+
|
107
|
+
|
108
|
+
def run(impact: dict):
|
109
|
+
should_run, grouped_inputs = _should_run(impact)
|
110
|
+
return flatten(map(_run_input(impact), grouped_inputs)) if should_run else []
|
@@ -34,7 +34,7 @@ def _should_run(site: dict):
|
|
34
34
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
35
35
|
waterSalinity=waterSalinity)
|
36
36
|
|
37
|
-
should_run = all([0 < waterSalinity < 500])
|
37
|
+
should_run = all([0 < (waterSalinity or 0) < 500])
|
38
38
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
39
39
|
return should_run
|
40
40
|
|
@@ -88,15 +88,15 @@ def _include_term_ids(term_id: str):
|
|
88
88
|
def _run_input(cycle: dict, input: dict):
|
89
89
|
term_id = input.get('term', {}).get('@id')
|
90
90
|
input_term_ids = _include_term_ids(term_id)
|
91
|
-
nitrogenContent = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent'), 0)
|
92
|
-
nitrogenContent_min = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent-min'), None)
|
93
|
-
nitrogenContent_max = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent-max'), None)
|
94
|
-
phosphateContentAsP2O5 = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5'), 0)
|
95
|
-
phosphateContentAsP2O5_min = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5-min'), None)
|
96
|
-
phosphateContentAsP2O5_max = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5-max'), None)
|
97
|
-
potassiumContentAsK2O = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O'), 0)
|
98
|
-
potassiumContentAsK2O_min = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O-min'), None)
|
99
|
-
potassiumContentAsK2O_max = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O-max'), None)
|
91
|
+
nitrogenContent = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent'), default=0)
|
92
|
+
nitrogenContent_min = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent-min'), default=None)
|
93
|
+
nitrogenContent_max = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent-max'), default=None)
|
94
|
+
phosphateContentAsP2O5 = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5'), default=0)
|
95
|
+
phosphateContentAsP2O5_min = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5-min'), default=None)
|
96
|
+
phosphateContentAsP2O5_max = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5-max'), default=None)
|
97
|
+
potassiumContentAsK2O = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O'), default=0)
|
98
|
+
potassiumContentAsK2O_min = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O-min'), default=None)
|
99
|
+
potassiumContentAsK2O_max = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O-max'), default=None)
|
100
100
|
|
101
101
|
from_units = input.get('term', {}).get('units')
|
102
102
|
input_value = list_sum(input.get('value'))
|
@@ -166,9 +166,9 @@ def _run_input(cycle: dict, input: dict):
|
|
166
166
|
def _should_run_input(cycle: dict, input: dict):
|
167
167
|
term_id = input.get('term', {}).get('@id')
|
168
168
|
has_value = list_sum(input.get('value', [])) > 0
|
169
|
-
nitrogenContent = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent'), None)
|
170
|
-
phosphateContentAsP2O5 = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5'), None)
|
171
|
-
potassiumContentAsK2O = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O'), None)
|
169
|
+
nitrogenContent = safe_parse_float(get_term_lookup(term_id, 'nitrogenContent'), default=None)
|
170
|
+
phosphateContentAsP2O5 = safe_parse_float(get_term_lookup(term_id, 'phosphateContentAsP2O5'), default=None)
|
171
|
+
potassiumContentAsK2O = safe_parse_float(get_term_lookup(term_id, 'potassiumContentAsK2O'), default=None)
|
172
172
|
|
173
173
|
# skip inputs that already have all the inlcuded term with a value
|
174
174
|
inputs = cycle.get('inputs', [])
|
@@ -163,7 +163,7 @@ def _should_group_landCover(management_node: dict):
|
|
163
163
|
)
|
164
164
|
|
165
165
|
|
166
|
-
def
|
166
|
+
def _get_changes(country_id: str, end_year: int) -> tuple[dict, bool]:
|
167
167
|
"""
|
168
168
|
For each entry in ALL_LAND_USE_TERMS, creates a key: value in output dictionary, also TOTAL
|
169
169
|
"""
|
@@ -178,7 +178,7 @@ def get_changes(country_id: str, end_year: int) -> tuple[dict, bool]:
|
|
178
178
|
)
|
179
179
|
for land_use_term in ALL_LAND_USE_TERMS + [LAND_AREA]
|
180
180
|
}
|
181
|
-
missing_changes =
|
181
|
+
missing_changes = [k for k, v in changes_dict.items() if v is None]
|
182
182
|
changes_dict = {k: v if v is not None else 0 for k, v in changes_dict.items()}
|
183
183
|
changes_dict[TOTAL_AGRICULTURAL_CHANGE] = (
|
184
184
|
float(changes_dict.get(TOTAL_CROPLAND, 0)) + float(changes_dict.get(PERMANENT_PASTURE, 0))
|
@@ -609,7 +609,7 @@ def _should_run_historical_land_use_change_single_crop(
|
|
609
609
|
) -> tuple[bool, dict]:
|
610
610
|
"""Calculate land use change percentages for a single management node/crop."""
|
611
611
|
# (C-H).
|
612
|
-
changes, missing_changes =
|
612
|
+
changes, missing_changes = _get_changes(country_id=country_id, end_year=end_year)
|
613
613
|
|
614
614
|
# (L). Estimate maximum forest loss
|
615
615
|
forest_loss = _estimate_maximum_forest_change(
|
@@ -749,12 +749,13 @@ def _should_run_historical_land_use_change_single_crop(
|
|
749
749
|
land_use_type=land_use_type,
|
750
750
|
country_id=country_id,
|
751
751
|
changes=log_as_table(changes),
|
752
|
+
missing_changes=log_as_table(missing_changes),
|
752
753
|
site_area=log_as_table(capped_site_area),
|
753
754
|
sum_of_site_areas_is_100=sum_of_site_areas_is_100,
|
754
755
|
site_type_allowed=site_type_allowed
|
755
756
|
)
|
756
757
|
|
757
|
-
should_run = all([
|
758
|
+
should_run = all([len(missing_changes) == 0, country_id, site_type_allowed, sum_of_site_areas_is_100])
|
758
759
|
logShouldRun(site, MODEL, term.get("@id"), should_run, model_key=MODEL_KEY)
|
759
760
|
|
760
761
|
return should_run, capped_site_area
|
@@ -831,7 +832,8 @@ def _should_run(site: dict) -> tuple[bool, list, dict]:
|
|
831
832
|
land_use_type=land_use_type,
|
832
833
|
allowed_land_use_types=';'.join(ALLOWED_LAND_USE_TYPES),
|
833
834
|
has_no_prior_land_cover_data=has_no_prior_land_cover_data,
|
834
|
-
management_nodes=log_as_table([_omit(n, ['term']) for n in relevant_nodes])
|
835
|
+
management_nodes=log_as_table([_omit(n, ['term']) for n in relevant_nodes]),
|
836
|
+
should_run_nodes=should_run_nodes)
|
835
837
|
|
836
838
|
should_run = all([land_use_type, has_no_prior_land_cover_data, should_run_nodes])
|
837
839
|
logShouldRun(site, MODEL, None, should_run, model_key=MODEL_KEY)
|
@@ -66,7 +66,7 @@ def _should_run(cycle: dict):
|
|
66
66
|
) or next(
|
67
67
|
(p for p in product.get('properties', []) if p.get('term', {}).get('@id').endswith('PerHead')), {}
|
68
68
|
)
|
69
|
-
propertyPerHead_value = safe_parse_float(propertyPerHead.get('value'), None)
|
69
|
+
propertyPerHead_value = safe_parse_float(propertyPerHead.get('value'), default=None)
|
70
70
|
|
71
71
|
# make sure the `liveAnimal` Term is not already present as a Product or Input
|
72
72
|
term_id = get_liveAnimal_term_id(product, model_key=MODEL_KEY)
|
@@ -95,7 +95,7 @@ _INPUT_RULES = {
|
|
95
95
|
TermTermType.INORGANICFERTILISER.value: (
|
96
96
|
(
|
97
97
|
TermTermType.INORGANICFERTILISER.value, # Lookup column
|
98
|
-
lambda x: safe_parse_float(x) > 0, # Condition
|
98
|
+
lambda x: safe_parse_float(x, default=0) > 0, # Condition
|
99
99
|
_INORGANIC_NITROGEN_FERTILISER_USED_TERM_ID # New term.
|
100
100
|
),
|
101
101
|
),
|
@@ -45,7 +45,7 @@ def _should_run(site: dict):
|
|
45
45
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
46
46
|
temperature=temperature)
|
47
47
|
|
48
|
-
should_run = temperature > 0
|
48
|
+
should_run = all([(temperature or 0) > 0])
|
49
49
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
50
50
|
return should_run, temperature
|
51
51
|
|
@@ -189,8 +189,8 @@ def _run_calculation(site: dict, depth_key: str, measurement_nodes: list[dict])
|
|
189
189
|
A list of `organicCarbonPerHa` [Measurement nodes](https://www.hestia.earth/schema/Measurement).
|
190
190
|
"""
|
191
191
|
split = depth_key.split('_') # "a_to_b"
|
192
|
-
depth_upper = safe_parse_float(split[0])
|
193
|
-
depth_lower = safe_parse_float(split[2])
|
192
|
+
depth_upper = safe_parse_float(split[0], default=0)
|
193
|
+
depth_lower = safe_parse_float(split[2], default=0)
|
194
194
|
|
195
195
|
soil_bulk_density_nodes = [
|
196
196
|
node for node in measurement_nodes if node.get('term', {}).get('@id') == SOIL_BULK_DENSITY_TERM_ID
|
@@ -34,7 +34,7 @@ def _should_run(site: dict):
|
|
34
34
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
35
35
|
waterSalinity=waterSalinity)
|
36
36
|
|
37
|
-
should_run = all([waterSalinity > 18000])
|
37
|
+
should_run = all([(waterSalinity or 0) > 18000])
|
38
38
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
39
39
|
return should_run
|
40
40
|
|