hestia-earth-models 0.67.0__py3-none-any.whl → 0.68.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/aware/scarcityWeightedWaterUse.py +5 -6
- hestia_earth/models/blonkConsultants2016/ch4ToAirNaturalVegetationBurning.py +1 -1
- hestia_earth/models/blonkConsultants2016/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +1 -1
- hestia_earth/models/blonkConsultants2016/n2OToAirNaturalVegetationBurningDirect.py +1 -1
- hestia_earth/models/blonkConsultants2016/utils.py +9 -9
- hestia_earth/models/cache_sites.py +26 -14
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandOccupation.py +2 -2
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +2 -2
- hestia_earth/models/chaudharyBrooks2018/utils.py +13 -8
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +2 -3
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +1 -1
- hestia_earth/models/cml2001Baseline/resourceUseEnergyDepletionDuringCycle.py +5 -10
- hestia_earth/models/config/Cycle.json +15 -0
- hestia_earth/models/config/ImpactAssessment.json +14 -1
- hestia_earth/models/config/Site.json +8 -0
- hestia_earth/models/cycle/completeness/freshForage.py +7 -3
- hestia_earth/models/cycle/excretaKgMass.py +2 -2
- hestia_earth/models/cycle/inorganicFertiliser.py +67 -17
- hestia_earth/models/cycle/materialAndSubstrate.py +3 -2
- hestia_earth/models/cycle/pastureGrass.py +3 -3
- hestia_earth/models/dammgen2009/noxToAirExcreta.py +1 -1
- hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +1 -1
- hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +2 -6
- hestia_earth/models/emissionNotRelevant/__init__.py +4 -4
- hestia_earth/models/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +60 -46
- hestia_earth/models/environmentalFootprintV3_1/photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +36 -0
- hestia_earth/models/environmentalFootprintV3_1/scarcityWeightedWaterUse.py +2 -2
- hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandOccupation.py +9 -8
- hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandTransformation.py +45 -34
- hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexTotalLandUseEffects.py +24 -21
- hestia_earth/models/faostat2018/coldCarcassWeightPerHead.py +2 -2
- hestia_earth/models/faostat2018/coldDressedCarcassWeightPerHead.py +2 -2
- hestia_earth/models/faostat2018/liveweightPerHead.py +7 -8
- hestia_earth/models/faostat2018/product/price.py +34 -28
- hestia_earth/models/faostat2018/readyToCookWeightPerHead.py +2 -2
- hestia_earth/models/faostat2018/utils.py +15 -27
- hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +16 -9
- hestia_earth/models/geospatialDatabase/altitude.py +60 -0
- hestia_earth/models/geospatialDatabase/croppingIntensity.py +1 -1
- hestia_earth/models/geospatialDatabase/ecoClimateZone.py +2 -2
- hestia_earth/models/geospatialDatabase/longFallowRatio.py +1 -1
- hestia_earth/models/geospatialDatabase/utils.py +4 -1
- hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +2 -3
- hestia_earth/models/haversineFormula/transport/distance.py +3 -3
- hestia_earth/models/hestia/landCover.py +72 -45
- hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +1 -1
- hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +1 -1
- hestia_earth/models/hestia/seed_emissions.py +11 -7
- hestia_earth/models/impact_assessment/__init__.py +3 -3
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/animal/fatContent.py +1 -1
- hestia_earth/models/ipcc2019/animal/hoursWorkedPerDay.py +1 -1
- hestia_earth/models/ipcc2019/animal/liveweightGain.py +1 -1
- hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +1 -1
- hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +1 -1
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +1 -1
- hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +1 -1
- hestia_earth/models/ipcc2019/animal/trueProteinContent.py +1 -1
- hestia_earth/models/ipcc2019/animal/utils.py +5 -7
- hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +2 -2
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +6 -7
- hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +5 -3
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +1 -1
- hestia_earth/models/ipcc2019/croppingDuration.py +3 -6
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +947 -0
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +4 -4
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +1 -1
- hestia_earth/models/ipcc2019/pastureGrass.py +1 -1
- hestia_earth/models/koble2014/residueBurnt.py +5 -7
- hestia_earth/models/koble2014/residueRemoved.py +5 -7
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/log.py +1 -1
- hestia_earth/models/mocking/search-results.json +3477 -1045
- hestia_earth/models/site/management.py +1 -1
- hestia_earth/models/site/post_checks/__init__.py +3 -2
- hestia_earth/models/site/post_checks/country.py +9 -0
- hestia_earth/models/site/pre_checks/__init__.py +3 -2
- hestia_earth/models/site/pre_checks/country.py +9 -0
- hestia_earth/models/utils/__init__.py +1 -16
- hestia_earth/models/utils/blank_node.py +89 -36
- hestia_earth/models/utils/completeness.py +3 -2
- hestia_earth/models/utils/cycle.py +5 -4
- hestia_earth/models/utils/ecoClimateZone.py +2 -2
- hestia_earth/models/utils/emission.py +5 -5
- hestia_earth/models/utils/feedipedia.py +6 -6
- hestia_earth/models/utils/impact_assessment.py +6 -6
- hestia_earth/models/utils/indicator.py +9 -7
- hestia_earth/models/utils/inorganicFertiliser.py +4 -6
- hestia_earth/models/utils/input.py +6 -5
- hestia_earth/models/utils/lookup.py +35 -105
- hestia_earth/models/utils/management.py +4 -4
- hestia_earth/models/utils/measurement.py +6 -7
- hestia_earth/models/utils/method.py +20 -0
- hestia_earth/models/utils/practice.py +4 -5
- hestia_earth/models/utils/product.py +4 -5
- hestia_earth/models/utils/property.py +12 -22
- hestia_earth/models/utils/site.py +14 -8
- hestia_earth/models/utils/term.py +27 -1
- hestia_earth/models/version.py +1 -1
- hestia_earth/orchestrator/log.py +0 -11
- hestia_earth/orchestrator/models/__init__.py +17 -4
- hestia_earth/orchestrator/strategies/run/add_blank_node_if_missing.py +2 -20
- {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/RECORD +159 -151
- tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +3 -3
- tests/models/cml2001Baseline/test_resourceUseEnergyDepletionDuringCycle.py +68 -35
- tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
- tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
- tests/models/cycle/test_concentrateFeed.py +1 -1
- tests/models/cycle/test_energyContentLowerHeatingValue.py +1 -1
- tests/models/cycle/test_excretaKgMass.py +1 -1
- tests/models/cycle/test_feedConversionRatio.py +3 -3
- tests/models/cycle/test_pastureGrass.py +1 -1
- tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
- tests/models/environmentalFootprintV3_1/test_environmentalFootprintSingleOverallScore.py +38 -8
- tests/models/environmentalFootprintV3_1/test_photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +30 -0
- tests/models/environmentalFootprintV3_1/test_soilQualityIndexLandTransformation.py +65 -36
- tests/models/environmentalFootprintV3_1/test_soilQualityIndexTotalLandUseEffects.py +30 -7
- tests/models/faostat2018/product/test_price.py +27 -14
- tests/models/faostat2018/test_faostat_utils.py +4 -24
- tests/models/faostat2018/test_liveweightPerHead.py +9 -9
- tests/models/globalCropWaterModel2008/test_rootingDepth.py +7 -3
- tests/models/haversineFormula/transport/test_distance.py +1 -1
- tests/models/hestia/test_landCover.py +53 -5
- tests/models/ipcc2019/animal/test_pastureGrass.py +5 -3
- tests/models/ipcc2019/test_aboveGroundCropResidueTotal.py +4 -4
- tests/models/ipcc2019/test_belowGroundCropResidue.py +4 -4
- tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +10 -10
- tests/models/ipcc2019/test_croppingDuration.py +1 -1
- tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +83 -0
- tests/models/ipcc2019/test_organicCarbonPerHa.py +12 -12
- tests/models/ipcc2019/test_pastureGrass.py +5 -3
- tests/models/pooreNemecek2018/test_excretaKgN.py +5 -5
- tests/models/pooreNemecek2018/test_excretaKgVs.py +2 -2
- tests/models/site/post_checks/test_country.py +6 -0
- tests/models/site/pre_checks/test_cache_geospatialDatabase.py +1 -1
- tests/models/site/pre_checks/test_country.py +12 -0
- tests/models/site/test_management.py +1 -4
- tests/models/test_ecoinventV3.py +7 -3
- tests/models/utils/test_blank_node.py +17 -177
- tests/models/utils/test_dataCompleteness.py +5 -5
- tests/models/utils/test_emission.py +2 -2
- tests/models/utils/test_indicator.py +2 -2
- tests/models/utils/test_input.py +2 -2
- tests/models/utils/test_measurement.py +2 -4
- tests/models/utils/test_practice.py +4 -2
- tests/models/utils/test_product.py +2 -2
- tests/models/utils/test_property.py +4 -2
- tests/models/utils/test_site.py +7 -0
- tests/orchestrator/models/test_transformations.py +4 -1
- tests/orchestrator/strategies/run/test_add_blank_node_if_missing.py +4 -9
- hestia_earth/models/environmentalFootprintV3_1/utils.py +0 -17
- tests/models/utils/test_lookup.py +0 -10
- {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/top_level.txt +0 -0
@@ -185,7 +185,7 @@ def _gap_filled_start_date(land_cover_id: str, end_date: str, cycle: dict) -> di
|
|
185
185
|
cycle_duration = _get_cycle_duration(cycle, land_cover_id)
|
186
186
|
return {
|
187
187
|
"startDate": max(
|
188
|
-
_gap_filled_date_obj(end_date) - timedelta(days=cycle_duration)
|
188
|
+
_gap_filled_date_obj(end_date) - timedelta(days=cycle_duration - 1)
|
189
189
|
if cycle_duration else datetime.fromtimestamp(0),
|
190
190
|
_gap_filled_date_obj(cycle.get("startDate"), mode=DatestrGapfillMode.START)
|
191
191
|
if cycle.get("startDate") else datetime.fromtimestamp(0)
|
@@ -2,13 +2,14 @@ from os.path import dirname, abspath
|
|
2
2
|
import sys
|
3
3
|
|
4
4
|
from hestia_earth.models.utils import _run_in_serie
|
5
|
-
from . import cache
|
5
|
+
from . import cache, country
|
6
6
|
|
7
7
|
CURRENT_DIR = dirname(abspath(__file__)) + '/'
|
8
8
|
sys.path.append(CURRENT_DIR)
|
9
9
|
|
10
10
|
MODELS = [
|
11
|
-
cache.run
|
11
|
+
cache.run,
|
12
|
+
country.run
|
12
13
|
]
|
13
14
|
|
14
15
|
|
@@ -2,7 +2,7 @@ from os.path import dirname, abspath
|
|
2
2
|
import sys
|
3
3
|
|
4
4
|
from hestia_earth.models.utils import _run_in_serie
|
5
|
-
from . import cache_years, cache_geospatialDatabase, cache_sources
|
5
|
+
from . import cache_years, cache_geospatialDatabase, cache_sources, country
|
6
6
|
|
7
7
|
CURRENT_DIR = dirname(abspath(__file__)) + '/'
|
8
8
|
sys.path.append(CURRENT_DIR)
|
@@ -10,7 +10,8 @@ sys.path.append(CURRENT_DIR)
|
|
10
10
|
MODELS = [
|
11
11
|
cache_years.run,
|
12
12
|
cache_geospatialDatabase.run,
|
13
|
-
cache_sources.run
|
13
|
+
cache_sources.run,
|
14
|
+
country.run
|
14
15
|
]
|
15
16
|
|
16
17
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"""
|
2
|
+
Pre Checks Country
|
3
|
+
|
4
|
+
Load the complete country data from HESTIA to be able to use `subClassOf` for example.
|
5
|
+
"""
|
6
|
+
from hestia_earth.utils.api import download_hestia
|
7
|
+
|
8
|
+
|
9
|
+
def run(site: dict): return site | {'country': download_hestia(site.get('country', {}).get('@id'))}
|
@@ -8,10 +8,9 @@ import datetime
|
|
8
8
|
from functools import reduce
|
9
9
|
import operator
|
10
10
|
from pydash.objects import get
|
11
|
-
from typing import Any, Callable
|
11
|
+
from typing import Any, Callable
|
12
12
|
from hestia_earth.schema import SchemaType
|
13
13
|
from hestia_earth.utils.api import download_hestia
|
14
|
-
from hestia_earth.utils.model import linked_node
|
15
14
|
from hestia_earth.utils.tools import flatten, non_empty_list
|
16
15
|
from hestia_earth.utils.date import is_in_days, is_in_months
|
17
16
|
|
@@ -44,20 +43,6 @@ def _omit(values: dict, keys: list) -> dict: return {k: v for k, v in values.ite
|
|
44
43
|
def _include(value: dict, keys: list) -> dict: return {k: v for k, v in value.items() if k in keys}
|
45
44
|
|
46
45
|
|
47
|
-
def _include_model(node: dict, term_id: str):
|
48
|
-
term = download_hestia(term_id) or {}
|
49
|
-
return {**node, **({} if term.get('@id') is None else {'model': linked_node(term)})}
|
50
|
-
|
51
|
-
|
52
|
-
def _include_method(node: dict, term_id: Union[None, str, dict], key='method'):
|
53
|
-
term = (download_hestia(term_id) or {}) if isinstance(term_id, str) else term_id
|
54
|
-
return node | ({} if term is None or term.get('@id') is None else {key: linked_node(term)})
|
55
|
-
|
56
|
-
|
57
|
-
def _include_methodModel(node: dict, term_id: str):
|
58
|
-
return _include_method(node, term_id=term_id, key='methodModel')
|
59
|
-
|
60
|
-
|
61
46
|
def _run_in_serie(data: dict, models: list): return reduce(lambda prev, model: model(prev), models, data)
|
62
47
|
|
63
48
|
|
@@ -12,38 +12,48 @@ from typing import (
|
|
12
12
|
Optional,
|
13
13
|
Union
|
14
14
|
)
|
15
|
-
|
16
15
|
from dateutil import parser
|
17
16
|
from dateutil.relativedelta import relativedelta
|
18
17
|
from hestia_earth.schema import TermTermType
|
19
|
-
from hestia_earth.utils.api import download_hestia
|
20
18
|
from hestia_earth.utils.blank_node import ArrayTreatment, get_node_value
|
21
19
|
from hestia_earth.utils.model import filter_list_term_type
|
22
20
|
from hestia_earth.utils.tools import (
|
23
21
|
flatten,
|
24
22
|
list_sum,
|
23
|
+
list_average,
|
25
24
|
safe_parse_date,
|
26
25
|
safe_parse_float,
|
27
26
|
non_empty_list
|
28
27
|
)
|
29
|
-
|
30
|
-
from . import is_from_model, _filter_list_term_unit, is_iterable, full_date_str
|
31
|
-
from .constant import Units, get_atomic_conversion
|
32
|
-
from .lookup import (
|
28
|
+
from hestia_earth.utils.lookup_utils import (
|
33
29
|
is_model_siteType_allowed,
|
34
30
|
is_siteType_allowed,
|
35
|
-
is_product_id_allowed,
|
36
|
-
|
31
|
+
is_product_id_allowed,
|
32
|
+
is_product_termType_allowed,
|
33
|
+
is_input_id_allowed,
|
34
|
+
is_input_termType_allowed
|
37
35
|
)
|
36
|
+
|
37
|
+
from hestia_earth.models.log import debugValues, log_as_table
|
38
|
+
from . import is_from_model, _filter_list_term_unit, is_iterable, full_date_str
|
39
|
+
from .constant import Units, get_atomic_conversion
|
40
|
+
from .lookup import _node_value
|
38
41
|
from .property import get_node_property, get_node_property_value
|
39
|
-
from .term import get_lookup_value
|
40
|
-
from ..log import debugValues, log_as_table
|
42
|
+
from .term import get_lookup_value, download_term
|
41
43
|
|
42
44
|
# TODO: verify those values
|
43
45
|
MAX_DEPTH = 1000
|
44
46
|
OLDEST_DATE = '1800'
|
45
47
|
|
46
48
|
|
49
|
+
def group_by_term(values: list):
|
50
|
+
def group_by(groups: dict, value: dict):
|
51
|
+
key = value.get('term', {}).get('@id')
|
52
|
+
groups[key] = groups.get(key, []) + [value]
|
53
|
+
return groups
|
54
|
+
return reduce(group_by, values, {})
|
55
|
+
|
56
|
+
|
47
57
|
def merge_blank_nodes(source: list, new_values: list):
|
48
58
|
"""
|
49
59
|
Merge a list of blank nodes into an existing list of blank nodes.
|
@@ -114,29 +124,29 @@ def _module_term_id(term_id: str, module):
|
|
114
124
|
return getattr(module, 'TERM_ID', term_id_str).split(',')[0]
|
115
125
|
|
116
126
|
|
117
|
-
def _run_model_required(model: str,
|
118
|
-
siteType_allowed = is_model_siteType_allowed(model,
|
127
|
+
def _run_model_required(model: str, term_id: str, data: dict):
|
128
|
+
siteType_allowed = is_model_siteType_allowed(model, term_id, data)
|
119
129
|
|
120
130
|
run_required = all([siteType_allowed])
|
121
|
-
debugValues(data, model=model, term=
|
131
|
+
debugValues(data, model=model, term=term_id,
|
122
132
|
run_required=run_required,
|
123
133
|
siteType_allowed=siteType_allowed)
|
124
134
|
return run_required
|
125
135
|
|
126
136
|
|
127
|
-
def _run_required(model: str,
|
128
|
-
siteType_allowed = is_siteType_allowed(data,
|
129
|
-
product_id_allowed = is_product_id_allowed(data,
|
130
|
-
product_termType_allowed = is_product_termType_allowed(data,
|
131
|
-
input_id_allowed = is_input_id_allowed(data,
|
132
|
-
input_termType_allowed = is_input_termType_allowed(data,
|
137
|
+
def _run_required(model: str, term_id: str, data: dict):
|
138
|
+
siteType_allowed = is_siteType_allowed(data, term_id)
|
139
|
+
product_id_allowed = is_product_id_allowed(data, term_id)
|
140
|
+
product_termType_allowed = is_product_termType_allowed(data, term_id)
|
141
|
+
input_id_allowed = is_input_id_allowed(data, term_id)
|
142
|
+
input_termType_allowed = is_input_termType_allowed(data, term_id)
|
133
143
|
|
134
144
|
run_required = all([
|
135
145
|
siteType_allowed, product_id_allowed, product_termType_allowed, input_id_allowed, input_termType_allowed
|
136
146
|
])
|
137
147
|
# model is only used for logs here, skip logs if model not provided
|
138
148
|
if model:
|
139
|
-
debugValues(data, model=model, term=
|
149
|
+
debugValues(data, model=model, term=term_id,
|
140
150
|
siteType_allowed=siteType_allowed,
|
141
151
|
product_id_allowed=product_id_allowed,
|
142
152
|
product_termType_allowed=product_termType_allowed,
|
@@ -144,7 +154,7 @@ def _run_required(model: str, term: dict, data: dict):
|
|
144
154
|
input_termType_allowed=input_termType_allowed)
|
145
155
|
# logging this for the model would cause issues parsing statuses
|
146
156
|
if model != 'emissionNotRelevant':
|
147
|
-
debugValues(data, model=model, term=
|
157
|
+
debugValues(data, model=model, term=term_id, run_required=run_required)
|
148
158
|
return run_required
|
149
159
|
|
150
160
|
|
@@ -166,10 +176,9 @@ def is_run_required(model: str, term_id: str, node: dict):
|
|
166
176
|
bool
|
167
177
|
True if the model is required to run.
|
168
178
|
"""
|
169
|
-
term = download_hestia(term_id)
|
170
179
|
return (
|
171
|
-
(_run_model_required(model,
|
172
|
-
) if
|
180
|
+
(_run_model_required(model, term_id, node) if model else True) and _run_required(model, term_id, node)
|
181
|
+
) if term_id else True
|
173
182
|
|
174
183
|
|
175
184
|
def run_if_required(model: str, term_id: str, data: dict, module):
|
@@ -1271,7 +1280,7 @@ def get_inputs_from_properties(input: dict, term_types: Union[TermTermType, List
|
|
1271
1280
|
properties = (
|
1272
1281
|
input.get('properties') or
|
1273
1282
|
input.get('term', {}).get('defaultProperties') or
|
1274
|
-
|
1283
|
+
download_term(input.get('term', {})).get('defaultProperties')
|
1275
1284
|
)
|
1276
1285
|
inputs = non_empty_list([
|
1277
1286
|
{
|
@@ -1335,11 +1344,14 @@ def _node_from_group(nodes: list):
|
|
1335
1344
|
# `nodes` contain list with consecutive dates
|
1336
1345
|
return nodes[0] if len(nodes) == 1 else (
|
1337
1346
|
# if all nodes have the same dates, sum up the values
|
1338
|
-
nodes[0] |
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1347
|
+
nodes[0] | (
|
1348
|
+
{
|
1349
|
+
'value': _sum_nodes_value(nodes)
|
1350
|
+
} if _same_dates(nodes) else {
|
1351
|
+
'startDate': min(n.get('startDate') for n in nodes),
|
1352
|
+
'endDate': max(n.get('endDate') for n in nodes)
|
1353
|
+
}
|
1354
|
+
)
|
1343
1355
|
)
|
1344
1356
|
|
1345
1357
|
|
@@ -1349,7 +1361,7 @@ def _condense_nodes(nodes: list):
|
|
1349
1361
|
return flatten(map(_node_from_group, grouped_nodes))
|
1350
1362
|
|
1351
1363
|
|
1352
|
-
def
|
1364
|
+
def _group_nodes_by_value_and_properties(nodes: list) -> dict:
|
1353
1365
|
def _group_node(group: dict, node: dict):
|
1354
1366
|
value = node.get('value', [])
|
1355
1367
|
value = '-'.join(map(str, value if isinstance(value, list) else [value]))
|
@@ -1359,7 +1371,6 @@ def _group_nodes_to_condense(nodes: list) -> dict:
|
|
1359
1371
|
f"{p.get('value')}"
|
1360
1372
|
])) for p in node.get('properties', [])
|
1361
1373
|
]))
|
1362
|
-
# group by term, value, and properties
|
1363
1374
|
group_key = '-'.join(non_empty_list([
|
1364
1375
|
node.get('term', {}).get('@id', ''),
|
1365
1376
|
value,
|
@@ -1371,8 +1382,51 @@ def _group_nodes_to_condense(nodes: list) -> dict:
|
|
1371
1382
|
return reduce(_group_node, nodes, {})
|
1372
1383
|
|
1373
1384
|
|
1385
|
+
def _group_nodes_by_dates(nodes: list) -> dict:
|
1386
|
+
def _group_node(group: dict, node: dict):
|
1387
|
+
group_key = '-'.join(non_empty_list([
|
1388
|
+
node.get('term', {}).get('@id', ''),
|
1389
|
+
node.get('startDate'),
|
1390
|
+
node.get('endDate'),
|
1391
|
+
]))
|
1392
|
+
group[group_key] = group.get(group_key, []) + [node]
|
1393
|
+
return group
|
1394
|
+
|
1395
|
+
return reduce(_group_node, nodes, {})
|
1396
|
+
|
1397
|
+
|
1398
|
+
def _average_properties(properties: list):
|
1399
|
+
# group properties by term
|
1400
|
+
grouped_properties = group_by_term(properties)
|
1401
|
+
return [
|
1402
|
+
props[0] | {
|
1403
|
+
'value': list_average(non_empty_list([p.get('value') for p in props]), default=props[0].get('value'))
|
1404
|
+
}
|
1405
|
+
for props in grouped_properties.values()
|
1406
|
+
]
|
1407
|
+
|
1408
|
+
|
1409
|
+
def _merge_same_dates(nodes: list):
|
1410
|
+
# group by term, startDate and endDate
|
1411
|
+
grouped_nodes = _group_nodes_by_dates(nodes)
|
1412
|
+
|
1413
|
+
def merge_nodes(nodes: list):
|
1414
|
+
properties = flatten([n.get('properties', []) for n in nodes])
|
1415
|
+
return nodes[0] | (
|
1416
|
+
{
|
1417
|
+
'value': _sum_nodes_value(nodes)
|
1418
|
+
} | ({
|
1419
|
+
'properties': _average_properties(properties)
|
1420
|
+
} if properties else {})
|
1421
|
+
) if len(nodes) > 1 else nodes[0]
|
1422
|
+
|
1423
|
+
return list(map(merge_nodes, grouped_nodes.values()))
|
1424
|
+
|
1425
|
+
|
1374
1426
|
def condense_nodes(nodes: list) -> list:
|
1375
|
-
|
1427
|
+
# merge nodes with the same term and dates as they need to be unique
|
1428
|
+
values = _merge_same_dates(nodes)
|
1429
|
+
grouped_nodes = _group_nodes_by_value_and_properties(values)
|
1376
1430
|
return flatten(map(_condense_nodes, grouped_nodes.values()))
|
1377
1431
|
|
1378
1432
|
|
@@ -1446,13 +1500,13 @@ def most_relevant_blank_node_by_id(nodes: list, term_id: str, date: str):
|
|
1446
1500
|
PROPERTY_UNITS_CONVERSIONS = {
|
1447
1501
|
Units.KG.value: {
|
1448
1502
|
Units.MJ.value: [
|
1449
|
-
'
|
1503
|
+
'energyContentLowerHeatingValue', # "kg" to "mj"
|
1450
1504
|
]
|
1451
1505
|
},
|
1452
1506
|
Units.M3.value: {
|
1453
1507
|
Units.MJ.value: [
|
1454
1508
|
'density', # "m3" to "kg"
|
1455
|
-
'
|
1509
|
+
'energyContentLowerHeatingValue', # "kg" to "mj"
|
1456
1510
|
]
|
1457
1511
|
}
|
1458
1512
|
}
|
@@ -1506,7 +1560,6 @@ def convert_unit_properties(node_value: Union[int, float], node: dict, dest_unit
|
|
1506
1560
|
Convert a number `node_value` belonging to a term `node`, to unit `to_units` by chaining multiple unit conversions
|
1507
1561
|
together.
|
1508
1562
|
Uses terms properties for the conversion.
|
1509
|
-
Uses cached calls to download_hestia() internally for speedup
|
1510
1563
|
Returns None if no conversion possible.
|
1511
1564
|
"""
|
1512
1565
|
src_unit = node.get("units") or node.get('term', {}).get('units', "")
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Union
|
2
2
|
from hestia_earth.schema import Completeness, TermTermType
|
3
|
-
|
3
|
+
|
4
|
+
from .term import download_term
|
4
5
|
|
5
6
|
completeness_fields = Completeness().required
|
6
7
|
|
@@ -12,7 +13,7 @@ def _completeness_term_type(cycle: dict, term: Union[str, dict, TermTermType]):
|
|
12
13
|
|
13
14
|
|
14
15
|
def _get_term_type_completeness(cycle: dict, term: Union[str, dict]):
|
15
|
-
term =
|
16
|
+
term = download_term(term) if isinstance(term, str) else term
|
16
17
|
term_type = term.get('termType') if term else None
|
17
18
|
return cycle.get('completeness', {}).get(term_type, False)
|
18
19
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
from hestia_earth.schema import CycleFunctionalUnit, SiteSiteType, TermTermType, AnimalReferencePeriod
|
2
2
|
from hestia_earth.utils.model import filter_list_term_type, find_term_match, find_primary_product
|
3
3
|
from hestia_earth.utils.tools import list_sum, safe_parse_float, safe_parse_date, non_empty_list
|
4
|
+
from hestia_earth.utils.lookup_utils import is_siteType_allowed
|
4
5
|
|
5
6
|
from ..log import logRequirements, debugValues
|
6
|
-
from .lookup import all_factor_value
|
7
|
+
from .lookup import all_factor_value
|
7
8
|
from .term import get_lookup_value
|
8
9
|
from .property import get_node_property
|
9
10
|
from .completeness import _is_term_type_complete
|
@@ -344,7 +345,7 @@ def is_organic(cycle: dict):
|
|
344
345
|
`True` if the `Cycle` is organic, `False` otherwise.
|
345
346
|
"""
|
346
347
|
practices = filter_list_term_type(cycle.get('practices', []), TermTermType.STANDARDSLABELS)
|
347
|
-
return
|
348
|
+
return next((get_lookup_value(p.get('term', {}), 'isOrganic') == 'organic' for p in practices), False)
|
348
349
|
|
349
350
|
|
350
351
|
def is_irrigated(cycle: dict, **log_ars):
|
@@ -463,9 +464,9 @@ def get_animals_by_period(cycle: dict, period: AnimalReferencePeriod = AnimalRef
|
|
463
464
|
]
|
464
465
|
|
465
466
|
|
466
|
-
def get_allowed_sites(model: str, term_id: str,
|
467
|
+
def get_allowed_sites(model: str, term_id: str, cycle: dict):
|
467
468
|
sites = non_empty_list([cycle.get('site', None)]) + cycle.get('otherSites', [])
|
468
|
-
allowed_sites = [s for s in sites if is_siteType_allowed(s,
|
469
|
+
allowed_sites = [s for s in sites if is_siteType_allowed(s, term_id)]
|
469
470
|
allowed_site_ids = non_empty_list([s.get('@id', s.get('id')) for s in allowed_sites])
|
470
471
|
debugValues(cycle, model=model, term=term_id, site_ids=';'.join(allowed_site_ids))
|
471
472
|
return allowed_sites
|
@@ -36,8 +36,8 @@ def get_eco_climate_zone_value(node: dict, as_enum: bool = False) -> Union[int,
|
|
36
36
|
Parameters
|
37
37
|
----------
|
38
38
|
node : dict
|
39
|
-
A HESTIA [Site](https://
|
40
|
-
[Cycle](https://
|
39
|
+
A HESTIA [Site](https://hestia.earth/schema/Site) or
|
40
|
+
[Cycle](https://hestia.earth/schema/Cycle).
|
41
41
|
|
42
42
|
Returns
|
43
43
|
-------
|
@@ -1,22 +1,22 @@
|
|
1
1
|
from collections.abc import Iterable
|
2
2
|
from typing import Optional, Union
|
3
3
|
from hestia_earth.schema import EmissionMethodTier, SchemaType, TermTermType
|
4
|
-
from hestia_earth.utils.api import download_hestia
|
5
4
|
from hestia_earth.utils.model import linked_node
|
6
5
|
|
7
6
|
|
8
|
-
from . import
|
7
|
+
from . import flatten_args
|
8
|
+
from .term import download_term
|
9
9
|
from .blank_node import find_terms_value
|
10
|
+
from .method import include_methodModel
|
10
11
|
from .constant import Units, get_atomic_conversion
|
11
12
|
|
12
|
-
|
13
13
|
EMISSION_METHOD_TIERS = [e.value for e in EmissionMethodTier]
|
14
14
|
|
15
15
|
|
16
16
|
def _new_emission(term, model=None):
|
17
17
|
node = {'@type': SchemaType.EMISSION.value}
|
18
|
-
node['term'] = linked_node(term if isinstance(term, dict) else
|
19
|
-
return
|
18
|
+
node['term'] = linked_node(term if isinstance(term, dict) else download_term(term, TermTermType.EMISSION))
|
19
|
+
return include_methodModel(node, model)
|
20
20
|
|
21
21
|
|
22
22
|
def get_nh3_no3_nox_to_n(cycle: dict, nh3_term_id: str, no3_term_id: str, nox_term_id: str, allow_none: bool = False):
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from hestia_earth.utils.model import find_term_match
|
2
|
-
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
|
2
|
+
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, lookup_term_ids
|
3
3
|
from hestia_earth.utils.tools import non_empty_list, safe_parse_float
|
4
4
|
|
5
5
|
from hestia_earth.models.log import logShouldRun
|
@@ -11,9 +11,9 @@ DRY_MATTER_TERM_ID = 'dryMatter'
|
|
11
11
|
|
12
12
|
def get_feedipedia_properties():
|
13
13
|
lookup = download_lookup('property.csv')
|
14
|
-
term_ids = list(lookup.termid)
|
15
14
|
term_ids = [
|
16
|
-
term_id for term_id in
|
15
|
+
term_id for term_id in lookup_term_ids(lookup)
|
16
|
+
if get_table_value(lookup, 'termid', term_id, column_name('feedipediaName'))
|
17
17
|
]
|
18
18
|
return term_ids
|
19
19
|
|
@@ -25,7 +25,6 @@ def _should_rescale_by_dm(property_id: str):
|
|
25
25
|
|
26
26
|
|
27
27
|
def _dm_property(term_id: str, property_values: dict, dm_property_values: dict, dry_matter_property: dict):
|
28
|
-
blank_node = _new_property(term_id)
|
29
28
|
blank_node_data = {}
|
30
29
|
for property_key in property_values.keys():
|
31
30
|
new_dm_value = safe_parse_float(dry_matter_property.get(property_key))
|
@@ -37,7 +36,7 @@ def _dm_property(term_id: str, property_values: dict, dm_property_values: dict,
|
|
37
36
|
2
|
38
37
|
) if _should_rescale_by_dm(term_id) else old_property_value
|
39
38
|
blank_node_data[property_key] = new_value
|
40
|
-
return (
|
39
|
+
return (_new_property(term_id) | blank_node_data) if blank_node_data else None
|
41
40
|
|
42
41
|
|
43
42
|
def _map_properties(lookup, term_id: str, column_prefix: str):
|
@@ -74,7 +73,8 @@ def rescale_properties_from_dryMatter(model: str, node: dict, blank_nodes: list)
|
|
74
73
|
new_properties = non_empty_list([
|
75
74
|
exec_property(blank_node, p, dry_matter_property) for p in properties if all([
|
76
75
|
not find_term_match(all_properties, p),
|
77
|
-
p != DRY_MATTER_TERM_ID
|
76
|
+
p != DRY_MATTER_TERM_ID,
|
77
|
+
dry_matter_property
|
78
78
|
])
|
79
79
|
])
|
80
80
|
for prop in new_properties:
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from typing import Optional
|
2
2
|
from hestia_earth.schema import TermTermType
|
3
|
-
from hestia_earth.utils.lookup import download_lookup
|
4
3
|
from hestia_earth.utils.model import find_term_match, filter_list_term_type
|
5
4
|
from hestia_earth.utils.tools import list_sum, safe_parse_date
|
6
5
|
|
@@ -131,6 +130,7 @@ def impact_country_value(
|
|
131
130
|
lookup: str,
|
132
131
|
group_key: str = None,
|
133
132
|
country_fallback: bool = False,
|
133
|
+
default_no_values=None
|
134
134
|
) -> float:
|
135
135
|
"""
|
136
136
|
Calculate the value of the impact based on lookup factors and `site.country.@id`.
|
@@ -160,19 +160,19 @@ def impact_country_value(
|
|
160
160
|
nodes = filter_list_term_type(impact.get('emissionsResourceUse', []), term_type)
|
161
161
|
|
162
162
|
country_id = get_country_id(impact)
|
163
|
-
country_id = fallback_country(country_id, [
|
163
|
+
country_id = fallback_country(country_id, [lookup]) if country_fallback else country_id
|
164
164
|
|
165
165
|
values = list(map(_term_factor_value(model, term_id, lookup, country_id, group_key), nodes))
|
166
166
|
debugValues(impact, model=model, term=term_id,
|
167
167
|
values_used=log_as_table(values))
|
168
168
|
|
169
|
-
|
169
|
+
has_values = len(values) > 0
|
170
|
+
missing_values = set([v.get('id') for v in values if v.get('value') and v.get('coefficient') is None])
|
171
|
+
all_with_factors = not missing_values
|
170
172
|
values = [float((v.get('value') or 0) * (v.get('coefficient') or 0)) for v in values]
|
171
173
|
|
172
174
|
# fail if some factors are missing
|
173
|
-
return None if not all_with_factors else (
|
174
|
-
list_sum(values) if len(values) > 0 else None
|
175
|
-
)
|
175
|
+
return None if not all_with_factors else (list_sum(values) if has_values else default_no_values)
|
176
176
|
|
177
177
|
|
178
178
|
def impact_aware_value(model: str, term_id: str, impact: dict, lookup: str, group_key: str = None) -> float:
|
@@ -1,15 +1,17 @@
|
|
1
|
-
from hestia_earth.schema import SchemaType
|
2
|
-
from hestia_earth.utils.api import download_hestia
|
1
|
+
from hestia_earth.schema import SchemaType, TermTermType
|
3
2
|
from hestia_earth.utils.model import linked_node
|
4
3
|
|
5
|
-
from . import
|
4
|
+
from .method import include_methodModel
|
5
|
+
from .term import download_term
|
6
6
|
|
7
7
|
|
8
8
|
def _new_indicator(term, model=None, land_cover_id: str = None, previous_land_cover_id: str = None):
|
9
9
|
node = {'@type': SchemaType.INDICATOR.value}
|
10
|
-
node['term'] = linked_node(term if isinstance(term, dict) else
|
10
|
+
node['term'] = linked_node(term if isinstance(term, dict) else download_term(
|
11
|
+
term, TermTermType.CHARACTERISEDINDICATOR)
|
12
|
+
)
|
11
13
|
if land_cover_id:
|
12
|
-
node['landCover'] = linked_node(
|
14
|
+
node['landCover'] = linked_node(download_term(land_cover_id, TermTermType.LANDCOVER))
|
13
15
|
if previous_land_cover_id:
|
14
|
-
node['previousLandCover'] = linked_node(
|
15
|
-
return
|
16
|
+
node['previousLandCover'] = linked_node(download_term(previous_land_cover_id, TermTermType.LANDCOVER))
|
17
|
+
return include_methodModel(node, model)
|
@@ -1,18 +1,18 @@
|
|
1
1
|
from hestia_earth.schema import TermTermType
|
2
|
-
from hestia_earth.utils.lookup import
|
2
|
+
from hestia_earth.utils.lookup import download_lookup, extract_grouped_data, lookup_term_ids
|
3
3
|
from hestia_earth.utils.tools import safe_parse_float
|
4
4
|
from hestia_earth.utils.model import filter_list_term_type
|
5
5
|
|
6
|
-
from ..log import debugMissingLookup
|
7
6
|
from .term import get_lookup_value
|
8
7
|
from .fertiliser import get_fertilisers_from_inputs
|
8
|
+
from .lookup import get_region_lookup_value
|
9
9
|
|
10
10
|
BREAKDOWN_LOOKUP = 'region-inorganicFertiliser-fertGroupingNitrogen-breakdown.csv'
|
11
11
|
|
12
12
|
|
13
13
|
def get_terms():
|
14
14
|
lookup = download_lookup('inorganicFertiliser.csv', True)
|
15
|
-
return
|
15
|
+
return lookup_term_ids(lookup)
|
16
16
|
|
17
17
|
|
18
18
|
def get_term_lookup(term_id: str, col_name: str):
|
@@ -35,9 +35,7 @@ def get_NH3_emission_factor(term_id: str, soilPh: float, temperature: float):
|
|
35
35
|
|
36
36
|
|
37
37
|
def get_country_breakdown(model: str, term_id: str, country_id: str, col_name: str):
|
38
|
-
|
39
|
-
value = get_table_value(lookup, 'termid', country_id, column_name(col_name))
|
40
|
-
debugMissingLookup(BREAKDOWN_LOOKUP, 'termid', country_id, col_name, value, model=model, term=term_id)
|
38
|
+
value = get_region_lookup_value(BREAKDOWN_LOOKUP, country_id, col_name, model=model, term=term_id)
|
41
39
|
return safe_parse_float(value, None)
|
42
40
|
|
43
41
|
|
@@ -1,19 +1,20 @@
|
|
1
1
|
from hestia_earth.schema import SchemaType, TermTermType
|
2
|
-
from hestia_earth.utils.api import download_hestia
|
3
2
|
from hestia_earth.utils.model import find_term_match, linked_node, filter_list_term_type
|
4
3
|
from hestia_earth.utils.tools import list_sum, non_empty_list, list_average, flatten
|
5
4
|
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
|
6
5
|
|
7
|
-
from
|
8
|
-
from . import
|
6
|
+
from hestia_earth.models.log import logger
|
7
|
+
from . import _filter_list_term_unit, _load_calculated_node
|
9
8
|
from .constant import Units
|
10
9
|
from .blank_node import get_total_value, get_total_value_converted, get_lookup_value
|
10
|
+
from .term import download_term
|
11
|
+
from .method import include_model
|
11
12
|
|
12
13
|
|
13
14
|
def _new_input(term, model=None):
|
14
15
|
node = {'@type': SchemaType.INPUT.value}
|
15
|
-
node['term'] = linked_node(term if isinstance(term, dict) else
|
16
|
-
return
|
16
|
+
node['term'] = linked_node(term if isinstance(term, dict) else download_term(term))
|
17
|
+
return include_model(node, model)
|
17
18
|
|
18
19
|
|
19
20
|
def load_impacts(inputs: list):
|