hestia-earth-models 0.64.8__py3-none-any.whl → 0.64.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hestia-earth-models might be problematic. Click here for more details.

Files changed (37) hide show
  1. hestia_earth/models/cycle/siteArea.py +2 -1
  2. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +73 -82
  3. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +102 -116
  4. hestia_earth/models/environmentalFootprintV3/soilQualityIndexTotalLandUseEffects.py +27 -16
  5. hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +3 -2
  6. hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +3 -2
  7. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +69 -37
  8. hestia_earth/models/ipcc2019/animal/fatContent.py +38 -0
  9. hestia_earth/models/ipcc2019/animal/liveweightGain.py +3 -54
  10. hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +3 -54
  11. hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +38 -0
  12. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +38 -0
  13. hestia_earth/models/ipcc2019/animal/utils.py +87 -3
  14. hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +4 -10
  15. hestia_earth/models/mocking/search-results.json +265 -259
  16. hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +4 -1
  17. hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +4 -1
  18. hestia_earth/models/utils/__init__.py +5 -4
  19. hestia_earth/models/utils/impact_assessment.py +13 -4
  20. hestia_earth/models/version.py +1 -1
  21. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.9.dist-info}/METADATA +1 -1
  22. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.9.dist-info}/RECORD +37 -31
  23. tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +97 -66
  24. tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +137 -74
  25. tests/models/environmentalFootprintV3/test_soilQualityIndexTotalLandUseEffects.py +15 -10
  26. tests/models/frischknechtEtAl2000/test_ionisingRadiationKbqU235Eq.py +67 -44
  27. tests/models/ipcc2019/animal/test_fatContent.py +22 -0
  28. tests/models/ipcc2019/animal/test_liveweightGain.py +4 -2
  29. tests/models/ipcc2019/animal/test_liveweightPerHead.py +4 -2
  30. tests/models/ipcc2019/animal/test_pregnancyRateTotal.py +22 -0
  31. tests/models/ipcc2019/animal/test_trueProteinContent.py +22 -0
  32. tests/models/ipcc2019/animal/test_weightAtMaturity.py +2 -1
  33. tests/models/poschEtAl2008/test_terrestrialAcidificationPotentialAccumulatedExceedance.py +30 -17
  34. tests/models/poschEtAl2008/test_terrestrialEutrophicationPotentialAccumulatedExceedance.py +28 -14
  35. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.9.dist-info}/LICENSE +0 -0
  36. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.9.dist-info}/WHEEL +0 -0
  37. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.9.dist-info}/top_level.txt +0 -0
@@ -9,6 +9,7 @@ from hestia_earth.utils.model import filter_list_term_type, find_term_match
9
9
  from hestia_earth.utils.tools import list_sum
10
10
 
11
11
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
12
+ from hestia_earth.models.utils import square_meter_to_hectare
12
13
  from . import MODEL
13
14
 
14
15
  REQUIREMENTS = {
@@ -48,7 +49,7 @@ def _run(cycle: dict):
48
49
  animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
49
50
  stocking_density = find_term_match(
50
51
  cycle.get('practices', []), 'stockingDensityAnimalHousingAverage', {}).get('value', [])
51
- return round(list_sum([a.get('value') for a in animals]) / list_sum(stocking_density), 7)
52
+ return square_meter_to_hectare(round(list_sum([a.get('value') for a in animals]) / list_sum(stocking_density), 7))
52
53
 
53
54
 
54
55
  def _should_run(cycle: dict, site: dict, key=MODEL_KEY):
@@ -1,41 +1,37 @@
1
+ """
2
+ Characterises [soilQualityIndexLandOccupation](https://hestia.earth/term/soilQualityIndexLandOccupation)
3
+ based on an updated [LANCA model (De Laurentiis et al. 2019)](
4
+ http://publications.jrc.ec.europa.eu/repository/handle/JRC113865) and on the LANCA (Regionalised) Characterisation
5
+ Factors version 2.5 (Horn and Meier, 2018).
6
+ """
7
+ from typing import Tuple
8
+
1
9
  from hestia_earth.schema import TermTermType
2
10
  from hestia_earth.utils.lookup import download_lookup
3
- from hestia_earth.utils.tools import list_sum, non_empty_list
11
+ from hestia_earth.utils.model import filter_list_term_type
12
+ from hestia_earth.utils.tools import list_sum
4
13
 
5
14
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
6
- from hestia_earth.models.utils import hectar_to_square_meter, days_to_years
7
- from hestia_earth.models.utils.blank_node import most_relevant_blank_node_by_type
8
15
  from hestia_earth.models.utils.indicator import _new_indicator
9
16
  from hestia_earth.models.utils.landCover import get_pef_grouping
10
- from hestia_earth.models.utils.lookup import fallback_country
17
+ from hestia_earth.models.utils.lookup import fallback_country, _node_value
11
18
  from . import MODEL
12
19
  from .utils import get_coefficient_factor
20
+ from ..utils.impact_assessment import get_country_id
13
21
 
14
22
  REQUIREMENTS = {
15
23
  "ImpactAssessment": {
16
- "cycle": {
17
- "@type": "Cycle",
18
- "siteDuration": "> 0",
19
- "siteArea": "> 0",
20
- "site": {
21
- "siteType": "",
22
- "@type": "Site",
23
- "management": [{"@type": "Management", "value": "", "term.termType": "landCover"}],
24
- "country": {"@type": "Term", "termType": "region"}
25
- },
26
- "optional": {
27
- "otherSitesDuration": "> 0",
28
- "otherSitesArea": "> 0",
29
- "otherSites": [{
30
- "@type": "Site",
31
- "siteType": "",
32
- "management": [{"@type": "Management", "value": "", "term.termType": "landCover"}],
33
- "country": {"@type": "Term", "termType": "region"}
34
- }]
35
- }
36
- }
24
+ "optional": {"country": {"@type": "Term", "termType": "region"}},
25
+ "emissionsResourceUse": [{
26
+ "@type": "Indicator",
27
+ "value": ">0",
28
+ "term.@id": ["landOccupationInputsProduction", "landOccupationDuringCycle"],
29
+ "term.units": "m2*year",
30
+ "landCover": {"@type": "Term", "term.termType": "landCover"}
31
+ }]
37
32
  }
38
33
  }
34
+
39
35
  LOOKUPS = {
40
36
  "@doc": "Performs lookup on landCover.csv for column headers and region-pefTermGrouping-landOccupation.csv for CFs",
41
37
  "region-pefTermGrouping-landOccupation": "",
@@ -50,6 +46,8 @@ RETURNS = {
50
46
  TERM_ID = 'soilQualityIndexLandOccupation'
51
47
  LOOKUP = f"{list(LOOKUPS.keys())[1]}.csv"
52
48
 
49
+ authorised_indicators = ["landOccupationInputsProduction", "landOccupationDuringCycle"]
50
+
53
51
 
54
52
  def _indicator(value: float):
55
53
  indicator = _new_indicator(TERM_ID, MODEL)
@@ -57,73 +55,66 @@ def _indicator(value: float):
57
55
  return indicator
58
56
 
59
57
 
60
- def _run(sites: list):
61
- values = [site['coeff'] * hectar_to_square_meter(site['area']) * days_to_years(site['duration']) for site in sites]
62
- return _indicator(list_sum(values)) if values else None
63
-
64
-
65
- def _should_run(impact_assessment: dict):
66
- cycle = impact_assessment.get('cycle', {})
67
- end_date = cycle.get('endDate')
68
-
69
- has_site = bool(cycle.get('site', False))
70
- has_other_sites = bool(cycle.get('otherSites', []))
58
+ def _run(land_occupation_indicators: list):
59
+ values = [indicator['coefficient'] * indicator['area-by-year'] for indicator in land_occupation_indicators]
60
+ return _indicator(list_sum(values))
71
61
 
72
- all_sites = non_empty_list([cycle.get('site')] + cycle.get('otherSites', []))
73
- site_areas = [cycle.get('siteArea')] + cycle.get('otherSitesArea', [])
74
- site_durations = [cycle.get('siteDuration')] + cycle.get('otherSitesDuration', [])
75
62
 
76
- sites = [
77
- {
78
- 'site-type': site.get('siteType'),
79
- 'country-id': site.get('country', {}).get('@id'),
80
- 'area': site_areas[index] if len(site_areas) >= index + 1 else None,
81
- 'duration': site_durations[index] if len(site_durations) >= index + 1 else None,
82
- 'landCover-id': (most_relevant_blank_node_by_type(
83
- site.get("management", []),
84
- term_type=TermTermType.LANDCOVER.value,
85
- date=end_date
86
- ) or {}).get('term', {}).get('@id'),
87
- }
88
- for index, site in enumerate(all_sites)
63
+ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
64
+ land_occupation_indicators = [
65
+ i for i in filter_list_term_type(impact_assessment.get('emissionsResourceUse', []), TermTermType.RESOURCEUSE) if
66
+ i.get('landCover', {}).get('termType') == TermTermType.LANDCOVER.value and
67
+ i.get('term', {}).get('@id', '') in authorised_indicators
89
68
  ]
90
69
 
91
- sites = [
92
- site for site in sites
93
- if all([
94
- (site.get('area') or 0) > 0,
95
- (site.get('duration') or 0) > 0,
96
- site.get('landCover-id')
97
- ])
98
- ]
99
-
100
- sites = [
101
- site |
102
- {
103
- 'coeff': get_coefficient_factor(
104
- LOOKUP,
105
- fallback_country(site.get('country-id'), [download_lookup(LOOKUP)]),
106
- get_pef_grouping(site.get('landCover-id')),
70
+ found_land_occupation_indicators = [{
71
+ 'area-by-year': _node_value(land_occupation_indicator),
72
+ 'area-unit': land_occupation_indicator.get('term', {}).get("units"),
73
+ 'land-cover-id': land_occupation_indicator.get('landCover', {}).get("@id"),
74
+ 'country-id': get_country_id(impact_assessment),
75
+ 'area-by-year-is-valid': _node_value(land_occupation_indicator) is not None and _node_value(
76
+ land_occupation_indicator) > 0,
77
+ 'area-unit-is-valid': land_occupation_indicator.get('term', {}).get("units") == "m2*year",
78
+ 'used-country': fallback_country(get_country_id(impact_assessment), [download_lookup(LOOKUP)]),
79
+
80
+ } for land_occupation_indicator in land_occupation_indicators]
81
+
82
+ found_indicators_with_coefficient = [
83
+ indicator | {
84
+ 'coefficient': get_coefficient_factor(
85
+ LOOKUP, indicator['used-country'],
86
+ get_pef_grouping(indicator['land-cover-id']),
107
87
  term_id=TERM_ID
108
- )
109
- } for site in sites
88
+ ),
89
+ "using-fallback-country-region-world-CFs": indicator['used-country'] != indicator['country-id']
90
+ } for indicator in found_land_occupation_indicators
110
91
  ]
111
- valid_sites = [site for site in sites if site.get('coeff') is not None]
112
92
 
113
- has_valid_sites = bool(valid_sites)
93
+ has_valid_land_occupations = all(
94
+ [
95
+ indicator['area-by-year-is-valid'] and indicator['area-unit-is-valid']
96
+ for indicator in found_land_occupation_indicators
97
+ ]) if found_land_occupation_indicators else False
98
+
99
+ valid_indicator_with_coef = [indicator for indicator in found_indicators_with_coefficient if
100
+ indicator['coefficient'] is not None and
101
+ indicator['area-by-year-is-valid'] and
102
+ indicator['area-unit-is-valid']]
114
103
 
115
- logRequirements(cycle, model=MODEL, term=TERM_ID,
116
- has_valid_sites=has_valid_sites,
117
- has_site=has_site,
118
- has_other_sites=has_other_sites,
119
- valid_sites=log_as_table(valid_sites),
104
+ has_land_occupation_indicators = bool(land_occupation_indicators)
105
+
106
+ logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
107
+ has_land_occupation_indicators=has_land_occupation_indicators,
108
+ has_valid_land_occupations=has_valid_land_occupations,
109
+ land_occupation_indicators=log_as_table(found_indicators_with_coefficient)
120
110
  )
121
111
 
122
- should_run = all([has_valid_sites])
123
- logShouldRun(cycle, MODEL, TERM_ID, should_run)
124
- return should_run, valid_sites
112
+ should_run = has_land_occupation_indicators and has_valid_land_occupations
113
+
114
+ logShouldRun(impact_assessment, MODEL, TERM_ID, should_run)
115
+ return should_run, valid_indicator_with_coef
125
116
 
126
117
 
127
118
  def run(impact_assessment: dict):
128
- should_run, sites = _should_run(impact_assessment)
129
- return _run(sites) if should_run else None
119
+ should_run, land_occupation_indicators = _should_run(impact_assessment)
120
+ return _run(land_occupation_indicators) if should_run else None
@@ -4,53 +4,53 @@ based on an updated [LANCA model (De Laurentiis et al. 2019)](
4
4
  http://publications.jrc.ec.europa.eu/repository/handle/JRC113865) and on the LANCA (Regionalised) Characterisation
5
5
  Factors version 2.5 (Horn and Meier, 2018).
6
6
  """
7
- from typing import List
7
+ from typing import List, Tuple, Optional
8
8
 
9
9
  from hestia_earth.schema import TermTermType
10
10
  from hestia_earth.utils.lookup import download_lookup
11
11
  from hestia_earth.utils.model import filter_list_term_type
12
- from hestia_earth.utils.tools import list_sum, safe_parse_date, non_empty_list
12
+ from hestia_earth.utils.tools import list_sum
13
13
 
14
14
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
15
- from hestia_earth.models.utils import hectar_to_square_meter
16
- from hestia_earth.models.utils import pairwise
17
15
  from . import MODEL
18
16
  from .utils import get_coefficient_factor
17
+ from ..utils.impact_assessment import get_country_id
19
18
  from ..utils.indicator import _new_indicator
20
19
  from ..utils.landCover import get_pef_grouping
21
- from ..utils.lookup import fallback_country
20
+ from ..utils.lookup import fallback_country, _node_value
21
+ from ..utils.term import download_all_land_cover_terms
22
22
 
23
23
  REQUIREMENTS = {
24
24
  "ImpactAssessment": {
25
- "cycle": {
26
- "@type": "Cycle",
27
- "site": {
28
- "area": "> 0",
29
- "@type": "Site",
30
- "management": [{"@type": "Management", "term.termType": "landCover"}],
31
- "optional": {"country": {"@type": "Term", "termType": "region"}}
32
- },
33
- "optional": {
34
- "otherSitesArea": "> 0",
35
- "otherSites": [{
36
- "@type": "Site",
37
- "management": [{"@type": "Management", "term.termType": "landCover"}],
38
- "optional": {"country": {"@type": "Term", "termType": "region"}}
39
- }]
25
+ "emissionsResourceUse": [
26
+ {
27
+ "@type": "Indicator",
28
+ "term.units": "m2 / year",
29
+ "term.termType": "resourceUse",
30
+ "term.name": "Land transformation from",
31
+ "value": "> 0",
32
+ "landCover": {"@type": "Term", "term.termType": "landCover"}
40
33
  }
41
- }
34
+ ],
35
+ "optional": {"country": {"@type": "Term", "termType": "region"}}
42
36
  }
43
37
  }
44
38
 
39
+ # Note: CFs in `region-pefTermGrouping-landTransformation-from.csv` appear to be the opposite values as those in
40
+ # `region-pefTermGrouping-landTransformation-to.csv` but can be different in some cases.
45
41
  LOOKUPS = {
46
- "@doc": "Uses `landCover.csv` for column headers and region-pefTermGrouping-landTransformation-X.csv for to/from CFs. (CFs in `region-pefTermGrouping-landTransformation-from.csv` appear to be the opposite values as those in `region-pefTermGrouping-landTransformation-to.csv` but can be different in some cases)", # noqa: E501
47
- "region-pefTermGrouping-landTransformation-from": "",
48
- "region-pefTermGrouping-landTransformation-to": "",
42
+ "region-pefTermGrouping-landTransformation-from": "using country and `pefTermGrouping` from `landCover`",
43
+ "region-pefTermGrouping-landTransformation-to": "using country and `pefTermGrouping` from `landCover`",
49
44
  "landCover": "pefTermGrouping"
50
45
  }
51
46
 
52
- from_lookup_file = f"{list(LOOKUPS.keys())[1]}.csv"
53
- to_lookup_file = f"{list(LOOKUPS.keys())[2]}.csv"
47
+ from_lookup_file = f"{list(LOOKUPS.keys())[0]}.csv"
48
+ to_lookup_file = f"{list(LOOKUPS.keys())[1]}.csv"
49
+
50
+ LOOKUP = {
51
+ "from": from_lookup_file,
52
+ "to": to_lookup_file
53
+ }
54
54
 
55
55
  RETURNS = {
56
56
  "Indicator": {
@@ -67,116 +67,102 @@ def _indicator(value: float):
67
67
  return indicator
68
68
 
69
69
 
70
- def _run(sites: List[dict]):
71
- result = []
72
- for site in sites:
73
- values = [(transformation_from_factor + transformation_to_factor) * hectar_to_square_meter(site['area'])
74
- for transformation_from_factor, transformation_to_factor in site['transformation_factors']]
75
- result.append(list_sum(values))
76
- return _indicator(list_sum(result)) if result else None
70
+ def _run(transformations: List[dict]):
71
+ values = [(transformation['factor-from'] + transformation['factor-to']) * transformation['area'] for transformation
72
+ in transformations]
73
+ return _indicator(list_sum(values))
77
74
 
78
75
 
79
- def _should_run(impact_assessment: dict):
80
- cycle = impact_assessment.get('cycle', {})
76
+ def _extract_land_cover_from_indicator_id(indicator: dict) -> Optional[str]:
77
+ """
78
+ Given a indicator with term type `resourceUse` return the equivalent `landCover` term
79
+ """
80
+ term_in_id = indicator.get('term', {}).get('@id', '') \
81
+ .removeprefix("landTransformationFrom") \
82
+ .removesuffix("20YearAverageInputsProduction") \
83
+ .removesuffix("20YearAverageDuringCycle")
84
+ term_in_id = term_in_id[0].lower() + term_in_id[1:] if term_in_id else None
85
+ return term_in_id
81
86
 
82
- has_site = bool(cycle.get('site', {}))
83
- site_area = cycle.get('site', {}).get("area", False)
84
- has_area = site_area > 0
85
87
 
86
- has_other_sites = bool(cycle.get('otherSites', []))
88
+ def _is_valid_indicator(indicator: dict, land_cover_term_ids: list[str]) -> bool:
89
+ term_id = _extract_land_cover_from_indicator_id(indicator)
90
+ return term_id in land_cover_term_ids
87
91
 
88
- all_sites = non_empty_list([cycle.get('site')] + cycle.get('otherSites', []))
89
- site_areas = [cycle.get('site', {}).get('area')] + cycle.get('otherSitesArea', [])
90
92
 
91
- sites = [
92
- {
93
- 'site_id': site.get('@id', site.get('id')),
94
- 'transformation_pairs': list(pairwise(
95
- sorted(filter_list_term_type(site.get("management", []), TermTermType.LANDCOVER.value),
96
- key=lambda d: safe_parse_date(d['endDate'])))),
97
- 'country_id_str': site.get('country', {}).get('@id', ''),
98
- 'area': site_areas[index] if len(site_areas) >= index + 1 else None,
99
- }
100
- for index, site in enumerate(all_sites)
101
- ]
93
+ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
94
+ resource_uses = filter_list_term_type(impact_assessment.get('emissionsResourceUse', []), TermTermType.RESOURCEUSE)
95
+ land_cover_term_ids = [term.get("@id") for term in download_all_land_cover_terms()] if resource_uses else []
102
96
 
103
- sites = [
104
- site for site in sites
105
- if all([
106
- (site.get('area') or 0) > 0,
107
- site.get('transformation_pairs', [])
108
- ])
109
- ]
97
+ land_transformation_indicators = [i for i in resource_uses if _is_valid_indicator(i, land_cover_term_ids)]
110
98
 
111
- sites = [
112
- site |
99
+ found_transformations = [
113
100
  {
114
- 'column_names': [(get_pef_grouping(from_transformation['term']['@id']),
115
- get_pef_grouping(to_transformation['term']['@id']))
116
- for from_transformation, to_transformation in site['transformation_pairs']],
117
- } for site in sites
101
+ 'area': _node_value(transformation_indicator) * 20,
102
+ 'area-unit': transformation_indicator.get('term', {}).get("units"),
103
+ 'land-cover-id-from': _extract_land_cover_from_indicator_id(transformation_indicator),
104
+ 'land-cover-id-to': transformation_indicator.get('landCover', {}).get("@id"),
105
+ 'indicator-id': transformation_indicator.get('term', {}).get('@id', ''),
106
+ 'good-land-cover-term': transformation_indicator.get('landCover', {}).get('termType') == 'landCover',
107
+ 'country-id': get_country_id(impact_assessment),
108
+ 'area-is-valid': _node_value(transformation_indicator) is not None and _node_value(
109
+ transformation_indicator) > 0,
110
+ 'area-unit-is-valid': transformation_indicator.get('term', {}).get("units") == "m2 / year",
111
+ 'lookup-country': fallback_country(get_country_id(impact_assessment),
112
+ [download_lookup(from_lookup_file), download_lookup(to_lookup_file)]),
113
+ } for transformation_indicator in land_transformation_indicators
118
114
  ]
119
115
 
120
- has_lookup_column = lambda s: s['column_names'] and all([all(pair) for pair in s['column_names']]) # noqa: E731
121
- valid_sites = [site for site in sites if has_lookup_column(site)]
122
-
123
- has_valid_sites = bool(valid_sites)
124
-
125
- valid_sites = [
126
- site |
127
- {
128
- 'country_id': fallback_country(site['country_id_str'],
129
- [download_lookup(from_lookup_file), download_lookup(to_lookup_file)]
130
- )
131
- } for site in valid_sites
116
+ found_transformations_with_coefficient = [
117
+ transformation | {
118
+ "using-fallback-country-region-world-CFs": transformation['lookup-country'] != transformation['country-id'],
119
+ 'factor-from': get_coefficient_factor(
120
+ lookup_name=from_lookup_file,
121
+ country_id=transformation['lookup-country'],
122
+ term_id=TERM_ID,
123
+ occupation_type=get_pef_grouping(transformation['land-cover-id-from'])) if
124
+ transformation['land-cover-id-from'] else None,
125
+ 'factor-to': get_coefficient_factor(
126
+ lookup_name=to_lookup_file,
127
+ country_id=transformation['lookup-country'],
128
+ term_id=TERM_ID,
129
+ occupation_type=get_pef_grouping(transformation['land-cover-id-to'])) if
130
+ transformation['land-cover-id-to'] else None
131
+ } for transformation in found_transformations
132
132
  ]
133
133
 
134
- valid_sites = [
135
- site |
136
- {
137
- 'transformation_factors': [(get_coefficient_factor(lookup_name=from_lookup_file,
138
- country_id=site['country_id'], term_id=TERM_ID,
139
- occupation_type=from_transformation_header),
140
- get_coefficient_factor(lookup_name=to_lookup_file,
141
- country_id=site['country_id'], term_id=TERM_ID,
142
- occupation_type=to_transformation_header))
143
- for from_transformation_header, to_transformation_header in site['column_names']]
144
- } for site in valid_sites
134
+ valid_transformations_with_coef = [
135
+ t for t in found_transformations_with_coefficient if all([
136
+ t['area-is-valid'],
137
+ t['area-unit-is-valid'],
138
+ t['factor-from'] is not None,
139
+ t['factor-to'] is not None
140
+ ])
145
141
  ]
146
142
 
147
- log_equivalent_eu_pef_land_use_names = [
148
- [{
149
- 'site-id': site['site_id'],
150
- 'hestia-term': hestia_term,
151
- 'corine-term': corine_term,
152
- } for hestia_term, corine_term in site['column_names']
153
- ] for site in valid_sites]
154
-
155
- log_transformation_factors = [
156
- [{
157
- 'site-id': site['site_id'],
158
- 'country-id-used-for-factors': site['country_id'],
159
- 'country-id-in-input': site['country_id_str'],
160
- 'factor-from': from_transformation_header,
161
- 'factor-to': to_transformation_header,
162
- } for from_transformation_header, to_transformation_header in site['transformation_factors']
163
- ] for site in valid_sites]
143
+ has_land_transformation_indicators = bool(land_transformation_indicators)
144
+
145
+ all_transformations_are_valid = all(
146
+ [
147
+ all([t['area-is-valid'], t['area-unit-is-valid'], t['good-land-cover-term']])
148
+ for t in found_transformations_with_coefficient
149
+ ]
150
+ ) if found_transformations_with_coefficient else False
164
151
 
165
152
  logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
166
- has_site=has_site,
167
- has_area=has_area,
168
- has_other_sites=has_other_sites,
169
- has_valid_sites=has_valid_sites,
170
- equivalent_EU_PEF_landUse_names=log_as_table(log_equivalent_eu_pef_land_use_names),
171
- transformation_factors=log_as_table(log_transformation_factors)
153
+ has_land_occupation_indicators=has_land_transformation_indicators,
154
+ all_transformations_are_valid=all_transformations_are_valid,
155
+ has_valid_transformations_with_coef=bool(valid_transformations_with_coef),
156
+ found_transformations=log_as_table(found_transformations_with_coefficient)
172
157
  )
173
- should_run = has_valid_sites
174
158
 
175
- logShouldRun(impact_assessment, MODEL, TERM_ID, should_run)
159
+ should_run = has_land_transformation_indicators is False or all([has_land_transformation_indicators,
160
+ all_transformations_are_valid])
176
161
 
177
- return should_run, valid_sites
162
+ logShouldRun(impact_assessment, MODEL, TERM_ID, should_run)
163
+ return should_run, valid_transformations_with_coef
178
164
 
179
165
 
180
166
  def run(impact_assessment: dict):
181
- should_run, sites = _should_run(impact_assessment)
182
- return _run(sites) if should_run else None
167
+ should_run, transformations = _should_run(impact_assessment)
168
+ return _run(transformations) if should_run else None
@@ -5,6 +5,7 @@ http://publications.jrc.ec.europa.eu/repository/handle/JRC113865) and on the LAN
5
5
  Factors version 2.5 (Horn and Meier, 2018).
6
6
  """
7
7
  from hestia_earth.utils.model import find_term_match
8
+ from hestia_earth.utils.tools import list_sum
8
9
 
9
10
  from hestia_earth.models.log import logRequirements, logShouldRun
10
11
  from . import MODEL
@@ -35,32 +36,42 @@ def _indicator(value: float):
35
36
  return indicator
36
37
 
37
38
 
38
- def _run(land_occupation_indicator, transformation_indicator):
39
- value = land_occupation_indicator['value'] + transformation_indicator['value']
40
- return _indicator(value) if value else None
39
+ def _run(indicators: list):
40
+ values = [indicator['value'] for indicator in indicators]
41
+ return _indicator(list_sum(values))
41
42
 
42
43
 
43
- def _should_run(impactassessment: dict):
44
- land_occupation_indicator = find_term_match(impactassessment.get('emissionsResourceUse', []),
45
- "soilQualityIndexLandOccupation")
46
- transformation_indicator = find_term_match(impactassessment.get('emissionsResourceUse', []),
47
- "soilQualityIndexLandTransformation")
44
+ def _should_run(impactassessment: dict) -> tuple[bool, list]:
45
+ land_indicators = [
46
+ i for i in impactassessment.get('emissionsResourceUse', []) if
47
+ i.get('term', {}).get('@id', '') in ['soilQualityIndexLandOccupation', 'soilQualityIndexLandTransformation']
48
+ ]
49
+ has_indicators = bool(land_indicators)
48
50
 
49
- has_valid_values = all([isinstance(land_occupation_indicator.get('value', None), (int, float)),
50
- isinstance(transformation_indicator.get('value', None), (int, float))])
51
+ land_occupation_indicator = find_term_match(land_indicators, "soilQualityIndexLandOccupation",
52
+ default_val=None)
53
+ has_land_occupation_indicator = bool(land_occupation_indicator)
54
+
55
+ land_transformation_indicator = find_term_match(land_indicators, "soilQualityIndexLandTransformation",
56
+ default_val=None)
57
+ has_land_transformation_indicator = bool(land_transformation_indicator)
58
+
59
+ has_valid_values = all([isinstance(indicator.get('value', None), (int, float)) for indicator in land_indicators])
51
60
 
52
61
  logRequirements(impactassessment, model=MODEL, term=TERM_ID,
53
- transformation_indicator=transformation_indicator,
54
- land_occupation_indicator=land_occupation_indicator,
62
+ has_indicators=has_indicators,
63
+ has_land_occupation_indicator=has_land_occupation_indicator,
64
+ has_land_transformation_indicator=has_land_transformation_indicator,
55
65
  has_valid_values=has_valid_values
56
66
  )
57
67
 
58
- should_run = all([transformation_indicator, land_occupation_indicator, has_valid_values])
68
+ should_run = all([has_indicators, has_valid_values,
69
+ has_land_occupation_indicator, has_land_transformation_indicator])
59
70
 
60
71
  logShouldRun(impactassessment, MODEL, TERM_ID, should_run)
61
- return should_run, land_occupation_indicator, transformation_indicator
72
+ return should_run, land_indicators
62
73
 
63
74
 
64
75
  def run(impactassessment: dict):
65
- should_run, land_occupation_indicator, transformation_indicator = _should_run(impactassessment)
66
- return _run(land_occupation_indicator, transformation_indicator) if should_run else None
76
+ should_run, indicators = _should_run(impactassessment)
77
+ return _run(indicators) if should_run else None
@@ -20,7 +20,8 @@ LOOKUPS = {
20
20
  }
21
21
  RETURNS = {
22
22
  "Indicator": [{
23
- "value": ""
23
+ "value": "",
24
+ "landCover": ""
24
25
  }]
25
26
  }
26
27
  TERM_ID = 'landTransformationFromTemporaryCropland100YearAverageDuringCycle,landTransformationFromPermanentCropland100YearAverageDuringCycle' # noqa: E501
@@ -30,7 +31,7 @@ PERMANENT_TERM_ID = 'landTransformationFromPermanentCropland100YearAverageDuring
30
31
 
31
32
 
32
33
  def _indicator(term_id: str, value: float):
33
- indicator = _new_indicator(term_id, MODEL)
34
+ indicator = _new_indicator(term_id, MODEL, 'cropland')
34
35
  indicator['value'] = value
35
36
  return indicator
36
37
 
@@ -20,7 +20,8 @@ LOOKUPS = {
20
20
  }
21
21
  RETURNS = {
22
22
  "Indicator": [{
23
- "value": ""
23
+ "value": "",
24
+ "landCover": ""
24
25
  }]
25
26
  }
26
27
  TERM_ID = 'landTransformationFromTemporaryCropland20YearAverageDuringCycle,landTransformationFromPermanentCropland20YearAverageDuringCycle' # noqa: E501
@@ -30,7 +31,7 @@ PERMANENT_TERM_ID = 'landTransformationFromPermanentCropland20YearAverageDuringC
30
31
 
31
32
 
32
33
  def _indicator(term_id: str, value: float):
33
- indicator = _new_indicator(term_id, MODEL)
34
+ indicator = _new_indicator(term_id, MODEL, 'cropland')
34
35
  indicator['value'] = value
35
36
  return indicator
36
37