hestia-earth-models 0.72.2__py3-none-any.whl → 0.73.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.
- 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 +10 -9
- hestia_earth/models/cache_sites.py +8 -4
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +14 -11
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/utils.py +5 -3
- hestia_earth/models/config/Cycle.json +48 -7
- hestia_earth/models/config/ImpactAssessment.json +22 -0
- hestia_earth/models/cycle/completeness/electricityFuel.py +1 -1
- hestia_earth/models/cycle/completeness/freshForage.py +1 -1
- hestia_earth/models/cycle/completeness/soilAmendment.py +1 -1
- hestia_earth/models/cycle/input/hestiaAggregatedData.py +1 -2
- hestia_earth/models/cycle/product/economicValueShare.py +4 -2
- 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/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +1 -1
- hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandOccupation.py +11 -11
- hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandTransformation.py +14 -11
- 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 +32 -18
- 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 +7 -5
- 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/excretaKgMass.py +7 -9
- 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 +35 -21
- hestia_earth/models/hestia/stockingDensityAnimalHousingAverage.py +1 -1
- hestia_earth/models/hestia/totalNitrogenPerKgSoil.py +1 -1
- hestia_earth/models/hestia/waterSalinity.py +3 -2
- 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 +18 -10
- 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 +1614 -1610
- 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 +44 -6
- 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/site/grouped_measurement.py +1 -1
- 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 +15 -11
- 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/impact_assessment.py +29 -14
- 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 +6 -2
- hestia_earth/models/utils/measurement.py +4 -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.1.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/RECORD +138 -127
- 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/pooreNemecek2018/test_freshwaterWithdrawalsDuringCycle.py +12 -0
- tests/models/test_resourceUseNotRelevant.py +27 -0
- tests/models/{akagiEtAl2011AndIpcc2006/test_utils.py → utils/test_cropResidue.py} +6 -6
- tests/models/utils/test_impact_assessment.py +29 -13
- 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.1.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/top_level.txt +0 -0
- /tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +0 -0
@@ -1,22 +1,19 @@
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
2
|
+
from hestia_earth.utils.model import find_term_match
|
3
|
+
from hestia_earth.utils.tools import list_sum
|
2
4
|
|
3
5
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
4
6
|
from hestia_earth.models.utils.constant import Units, get_atomic_conversion
|
5
7
|
from hestia_earth.models.utils.emission import _new_emission
|
6
|
-
from hestia_earth.models.utils.input import total_excreta
|
7
|
-
from hestia_earth.models.utils.excretaManagement import get_lookup_factor
|
8
8
|
from . import MODEL
|
9
9
|
|
10
10
|
REQUIREMENTS = {
|
11
11
|
"Cycle": {
|
12
|
-
"
|
13
|
-
{"@type": "
|
12
|
+
"emissions": [
|
13
|
+
{"@type": "Emission", "value": "", "term.@id": "n2OToAirExcretaDirect"}
|
14
14
|
]
|
15
15
|
}
|
16
16
|
}
|
17
|
-
LOOKUPS = {
|
18
|
-
"excretaManagement": "EF_NO-N"
|
19
|
-
}
|
20
17
|
RETURNS = {
|
21
18
|
"Emission": [{
|
22
19
|
"value": "",
|
@@ -25,6 +22,7 @@ RETURNS = {
|
|
25
22
|
}
|
26
23
|
TERM_ID = 'noxToAirExcreta'
|
27
24
|
TIER = EmissionMethodTier.TIER_1.value
|
25
|
+
N2O_TERM_ID = 'n2OToAirExcretaDirect'
|
28
26
|
|
29
27
|
|
30
28
|
def _emission(value: float):
|
@@ -34,24 +32,22 @@ def _emission(value: float):
|
|
34
32
|
return emission
|
35
33
|
|
36
34
|
|
37
|
-
def _run(
|
38
|
-
value =
|
35
|
+
def _run(n2o: dict):
|
36
|
+
value = 0.1 * list_sum(n2o.get("value", [])) / get_atomic_conversion(Units.KG_N2O, Units.TO_N)
|
37
|
+
value = value * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
|
39
38
|
return [_emission(value)]
|
40
39
|
|
41
40
|
|
42
41
|
def _should_run(cycle: dict):
|
43
|
-
|
44
|
-
NO_N_EF = get_lookup_factor(cycle.get('practices', []), LOOKUPS['excretaManagement'])
|
42
|
+
n2o = find_term_match(cycle.get('emissions', []), N2O_TERM_ID)
|
45
43
|
|
46
|
-
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
47
|
-
excretaKgN=excretaKgN,
|
48
|
-
NO_N_EF=NO_N_EF)
|
44
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID, has_n2o=n2o is not None)
|
49
45
|
|
50
|
-
should_run = all([
|
46
|
+
should_run = all([n2o])
|
51
47
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
52
|
-
return should_run,
|
48
|
+
return should_run, n2o
|
53
49
|
|
54
50
|
|
55
51
|
def run(cycle: dict):
|
56
|
-
should_run,
|
57
|
-
return _run(
|
52
|
+
should_run, n2o = _should_run(cycle)
|
53
|
+
return _run(n2o) if should_run else []
|
@@ -79,7 +79,7 @@ def _emission(term_id: str, value: float, input: dict):
|
|
79
79
|
return emission
|
80
80
|
|
81
81
|
|
82
|
-
def _add_emission(cycle: dict, input: dict):
|
82
|
+
def _add_emission(cycle: dict, input: dict, **extra_logs):
|
83
83
|
input_term_id = input.get('term', {}).get('@id')
|
84
84
|
operation_term_id = input.get('operation', {}).get('@id')
|
85
85
|
animal_term_id = input.get('animal', {}).get('@id')
|
@@ -89,7 +89,7 @@ def _add_emission(cycle: dict, input: dict):
|
|
89
89
|
emissions = ecoinventV3_emissions(ecoinventName)
|
90
90
|
for emission_term_id, value in emissions:
|
91
91
|
# log run on each emission so we know it did run
|
92
|
-
logShouldRun(cycle, MODEL, input_term_id, True, methodTier=TIER, emission_id=emission_term_id)
|
92
|
+
logShouldRun(cycle, MODEL, input_term_id, True, methodTier=TIER, emission_id=emission_term_id, **extra_logs)
|
93
93
|
debugValues(cycle, model=MODEL, term=emission_term_id,
|
94
94
|
value=value,
|
95
95
|
coefficient=coefficient,
|
@@ -112,6 +112,10 @@ def _run_input(cycle: dict):
|
|
112
112
|
mappings = get_input_mappings(MODEL, cycle, input)
|
113
113
|
has_mappings = len(mappings) > 0
|
114
114
|
|
115
|
+
# grouping the inputs together in the logs
|
116
|
+
input_parent_term_id = input.get('parent', {}).get('@id')
|
117
|
+
extra_logs = {'input_group_id': input_parent_term_id} if input_parent_term_id else {}
|
118
|
+
|
115
119
|
# skip input that has background emissions we have already gap-filled (model run before)
|
116
120
|
has_no_gap_filled_background_emissions = no_gap_filled_background_emissions_func(input)
|
117
121
|
|
@@ -119,13 +123,14 @@ def _run_input(cycle: dict):
|
|
119
123
|
has_ecoinvent_mappings=has_mappings,
|
120
124
|
ecoinvent_mappings=';'.join([v[0] for v in mappings]),
|
121
125
|
has_no_gap_filled_background_emissions=has_no_gap_filled_background_emissions,
|
122
|
-
input_value=input_value
|
126
|
+
input_value=input_value,
|
127
|
+
**extra_logs)
|
123
128
|
|
124
129
|
should_run = all([has_mappings, has_no_gap_filled_background_emissions, input_value])
|
125
|
-
logShouldRun(cycle, MODEL, input_term_id, should_run, methodTier=TIER)
|
130
|
+
logShouldRun(cycle, MODEL, input_term_id, should_run, methodTier=TIER, **extra_logs)
|
126
131
|
|
127
|
-
grouped_emissions = reduce(_add_emission(cycle, input), mappings, {}) if should_run else {}
|
128
|
-
log_missing_emissions_func(input_term_id, list(grouped_emissions.keys()))
|
132
|
+
grouped_emissions = reduce(_add_emission(cycle, input, **extra_logs), mappings, {}) if should_run else {}
|
133
|
+
log_missing_emissions_func(input_term_id, list(grouped_emissions.keys()), **extra_logs)
|
129
134
|
return [
|
130
135
|
_emission(term_id, value * input_value, input)
|
131
136
|
for term_id, value in grouped_emissions.items()
|
@@ -19,4 +19,4 @@ def get_input_coefficient(model: str, cycle: dict, country_id: str, ecoinventNam
|
|
19
19
|
# find the ratio for the country / year
|
20
20
|
data = get_region_lookup_value(REGION_EMBER_SOURCES_LOOKUP_NAME, country_id, source_name, model=model)
|
21
21
|
percentage = extract_grouped_data(data, str(year))
|
22
|
-
return safe_parse_float(percentage, 0) / 100
|
22
|
+
return safe_parse_float(percentage, default=0) / 100
|
@@ -95,7 +95,8 @@ def group_fuel_inputs(inputs: list):
|
|
95
95
|
|
96
96
|
def _get_emissions_factor(animal: dict, lookup_col: str) -> float:
|
97
97
|
return safe_parse_float(
|
98
|
-
get_lookup_value(animal.get("term", {}), lookup_col, model=MODEL, term=animal.get("term", ""))
|
98
|
+
get_lookup_value(animal.get("term", {}), lookup_col, model=MODEL, term=animal.get("term", "")),
|
99
|
+
default=None
|
99
100
|
)
|
100
101
|
|
101
102
|
|
@@ -4,7 +4,7 @@ from hestia_earth.utils.tools import list_sum
|
|
4
4
|
from typing import List, Optional, Tuple
|
5
5
|
|
6
6
|
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table, debugValues
|
7
|
-
from hestia_earth.models.utils.
|
7
|
+
from hestia_earth.models.utils.term import get_lookup_value
|
8
8
|
from hestia_earth.models.utils.indicator import _new_indicator
|
9
9
|
from hestia_earth.models.utils.lookup import _node_value
|
10
10
|
from . import MODEL
|
@@ -60,17 +60,17 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
|
|
60
60
|
]
|
61
61
|
|
62
62
|
found_land_occupation_indicators = [{
|
63
|
-
'area-by-year': _node_value(
|
64
|
-
'area-unit':
|
65
|
-
'land-cover-id':
|
66
|
-
'country-id': get_country_id(impact_assessment),
|
67
|
-
'area-by-year-is-valid': _node_value(
|
68
|
-
|
69
|
-
'area-unit-is-valid':
|
70
|
-
'used-country': fallback_country(get_country_id(impact_assessment), [LOOKUP]),
|
71
|
-
'pef-grouping': get_pef_grouping(
|
72
|
-
|
73
|
-
} for
|
63
|
+
'area-by-year': _node_value(indicator),
|
64
|
+
'area-unit': indicator.get('term', {}).get("units"),
|
65
|
+
'land-cover-id': indicator.get('landCover', {}).get("@id"),
|
66
|
+
'country-id': get_country_id(impact_assessment, blank_node=indicator),
|
67
|
+
'area-by-year-is-valid': _node_value(indicator) is not None and _node_value(
|
68
|
+
indicator) > 0,
|
69
|
+
'area-unit-is-valid': indicator.get('term', {}).get("units") == "m2*year",
|
70
|
+
'used-country': fallback_country(get_country_id(impact_assessment, blank_node=indicator), [LOOKUP]),
|
71
|
+
'pef-grouping': get_pef_grouping(indicator.get('landCover', {}).get("@id"))
|
72
|
+
|
73
|
+
} for indicator in land_occupation_indicators]
|
74
74
|
|
75
75
|
found_indicators_with_coefficient = [
|
76
76
|
indicator | {
|
@@ -92,21 +92,24 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
|
|
92
92
|
|
93
93
|
found_transformations = [
|
94
94
|
{
|
95
|
-
'value': _node_value(
|
96
|
-
'land-cover-id-from':
|
97
|
-
'land-cover-id-to':
|
98
|
-
'indicator-id':
|
95
|
+
'value': _node_value(indicator),
|
96
|
+
'land-cover-id-from': indicator.get('previousLandCover', {}).get("@id"),
|
97
|
+
'land-cover-id-to': indicator.get('landCover', {}).get("@id"),
|
98
|
+
'indicator-id': indicator.get('term', {}).get('@id', ''),
|
99
99
|
'good-land-cover-term': all([
|
100
|
-
bool(
|
101
|
-
bool(
|
100
|
+
bool(indicator.get('landCover')),
|
101
|
+
bool(indicator.get('previousLandCover'))
|
102
102
|
]),
|
103
|
-
'country-id': get_country_id(impact_assessment),
|
103
|
+
'country-id': get_country_id(impact_assessment, blank_node=indicator),
|
104
104
|
'value-is-valid': (
|
105
|
-
_node_value(
|
106
|
-
_node_value(
|
105
|
+
_node_value(indicator) is not None and
|
106
|
+
_node_value(indicator) >= 0
|
107
107
|
),
|
108
|
-
'lookup-country': fallback_country(
|
109
|
-
|
108
|
+
'lookup-country': fallback_country(
|
109
|
+
get_country_id(impact_assessment, blank_node=indicator),
|
110
|
+
[from_lookup_file, to_lookup_file]
|
111
|
+
),
|
112
|
+
} for indicator in resource_uses
|
110
113
|
]
|
111
114
|
|
112
115
|
found_transformations_with_coefficient = [
|
@@ -55,7 +55,7 @@ def _product_value(product: dict, year: int, country_id: str):
|
|
55
55
|
groupingFAO = get_animalProduct_lookup_value(MODEL, product_id, FAO_LOOKUP_COLUMN)
|
56
56
|
|
57
57
|
data = get_region_lookup_value(LOOKUP_WEIGHT, country_id, groupingFAO, model=MODEL, term=TERM_ID)
|
58
|
-
average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), None)
|
58
|
+
average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), default=None)
|
59
59
|
# average_carcass_weight is in hg, divide by 10 to go back to kg
|
60
60
|
kg_carcass_weight = average_carcass_weight / 10 if average_carcass_weight else None
|
61
61
|
|
@@ -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
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
from hestia_earth.schema import TermTermType
|
2
2
|
from hestia_earth.utils.api import download_hestia
|
3
3
|
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data_closest_date
|
4
|
-
from hestia_earth.utils.tools import safe_parse_float, flatten
|
4
|
+
from hestia_earth.utils.tools import safe_parse_float, flatten, non_empty_list
|
5
5
|
|
6
|
-
from hestia_earth.models.log import logger, debugMissingLookup, logRequirements, logShouldRun, debugValues
|
6
|
+
from hestia_earth.models.log import logger, debugMissingLookup, logRequirements, logShouldRun, debugValues, log_as_table
|
7
7
|
from hestia_earth.models.utils.animalProduct import (
|
8
8
|
FAO_LOOKUP_COLUMN, FAO_EQUIVALENT_LOOKUP_COLUMN, get_animalProduct_lookup_value
|
9
9
|
)
|
@@ -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
|
|
@@ -151,24 +152,37 @@ def should_run_landTransformationFromCropland(term_id: str, impact: dict):
|
|
151
152
|
return should_run, indicators
|
152
153
|
|
153
154
|
|
155
|
+
def _map_indicator_value(impact: dict, start_year: int, end_year: int):
|
156
|
+
def mapper(indicator: dict):
|
157
|
+
country_id = get_country_id(impact, blank_node=indicator)
|
158
|
+
total, permanent, temporary = get_cropland_ratio(country_id, start_year, end_year)
|
159
|
+
return {
|
160
|
+
'landCover-id': indicator.get('landCover', {}).get('@id'),
|
161
|
+
'value': indicator.get('value'),
|
162
|
+
'country-id': country_id,
|
163
|
+
'diff-total-area': total,
|
164
|
+
'diff-temporary-area': temporary,
|
165
|
+
'diff-permanent-area': permanent
|
166
|
+
} if total is not None else None
|
167
|
+
return mapper
|
168
|
+
|
169
|
+
|
154
170
|
def run_landTransformationFromCropland(term_id: str, impact: dict, indicators: list, years: int):
|
155
|
-
country_id = get_country_id(impact)
|
156
171
|
end_year = impact_end_year(impact)
|
157
|
-
|
172
|
+
|
173
|
+
values = non_empty_list(map(_map_indicator_value(impact, end_year - years, end_year), indicators))
|
158
174
|
|
159
175
|
debugValues(impact, model=MODEL, term_id=term_id,
|
160
|
-
|
161
|
-
diff_permanent_area=permanent,
|
162
|
-
diff_total_area=total)
|
176
|
+
indicators_used=log_as_table(values))
|
163
177
|
|
164
178
|
return flatten([
|
165
179
|
[
|
166
|
-
_new_indicator(term_id, MODEL,
|
167
|
-
'value':
|
180
|
+
_new_indicator(term_id, MODEL, value.get('landCover-id'), 'annualCropland') | {
|
181
|
+
'value': value.get('value') * value.get('diff-temporary-area') / value.get('diff-total-area')
|
168
182
|
},
|
169
|
-
_new_indicator(term_id, MODEL,
|
170
|
-
'value':
|
183
|
+
_new_indicator(term_id, MODEL, value.get('landCover-id'), 'permanentCropland') | {
|
184
|
+
'value': value.get('value') * value.get('diff-permanent-area') / value.get('diff-total-area')
|
171
185
|
}
|
172
186
|
]
|
173
|
-
for
|
174
|
-
])
|
187
|
+
for value in values
|
188
|
+
])
|
@@ -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):
|
@@ -101,17 +101,19 @@ def _get_region_area_size(site: dict):
|
|
101
101
|
|
102
102
|
|
103
103
|
def get_area_size(site: dict):
|
104
|
-
return
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
return _cached_value(site, CACHE_AREA_SIZE) or (
|
105
|
+
None if has_coordinates(site) else (
|
106
|
+
# fallback if `boundary` provided but no `boundaryArea` was computed
|
107
|
+
site.get('boundaryArea') or _get_boundary_area_size(site.get('boundary'))
|
108
|
+
) if has_boundary(site) else _get_region_area_size(site)
|
109
|
+
)
|
108
110
|
|
109
111
|
|
110
112
|
def _is_below_max_size(term: str, site: dict) -> bool:
|
111
113
|
current_size = _cached_value(site, CACHE_AREA_SIZE) or get_area_size(site)
|
112
114
|
if current_size is not None:
|
113
115
|
logRequirements(site, model=MODEL, term=term,
|
114
|
-
current_size=
|
116
|
+
current_size=round(float(current_size), 5),
|
115
117
|
max_area_size=MAX_AREA_SIZE)
|
116
118
|
return current_size <= MAX_AREA_SIZE
|
117
119
|
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.term 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 []
|