hestia-earth-models 0.59.5__py3-none-any.whl → 0.59.7__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 (46) hide show
  1. hestia_earth/models/cache_sites.py +6 -8
  2. hestia_earth/models/cycle/animal/milkYield.py +86 -0
  3. hestia_earth/models/cycle/endDate.py +50 -0
  4. hestia_earth/models/cycle/inorganicFertiliser.py +3 -2
  5. hestia_earth/models/cycle/milkYield.py +8 -3
  6. hestia_earth/models/cycle/pre_checks/__init__.py +1 -2
  7. hestia_earth/models/cycle/siteDuration.py +1 -1
  8. hestia_earth/models/cycle/startDate.py +42 -0
  9. hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +9 -6
  10. hestia_earth/models/faostat2018/liveweightPerHead.py +77 -41
  11. hestia_earth/models/faostat2018/product/price.py +43 -57
  12. hestia_earth/models/faostat2018/utils.py +10 -2
  13. hestia_earth/models/geospatialDatabase/utils.py +0 -1
  14. hestia_earth/models/haversineFormula/transport/distance.py +6 -3
  15. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
  16. hestia_earth/models/ipcc2019/co2ToAirLimeHydrolysis.py +1 -1
  17. hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +2 -7
  18. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +26 -6
  19. hestia_earth/models/ipcc2019/pastureGrass.py +2 -1
  20. hestia_earth/models/linkedImpactAssessment/__init__.py +3 -3
  21. hestia_earth/models/mocking/search-results.json +244 -232
  22. hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +58 -0
  23. hestia_earth/models/site/management.py +3 -1
  24. hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +2 -2
  25. hestia_earth/models/utils/__init__.py +4 -1
  26. hestia_earth/models/utils/animalProduct.py +6 -4
  27. hestia_earth/models/utils/blank_node.py +3 -2
  28. hestia_earth/models/utils/product.py +9 -1
  29. hestia_earth/models/utils/property.py +2 -1
  30. hestia_earth/models/utils/site.py +7 -4
  31. hestia_earth/models/version.py +1 -1
  32. {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/METADATA +1 -1
  33. {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/RECORD +44 -38
  34. tests/models/cycle/animal/test_milkYield.py +43 -0
  35. tests/models/cycle/test_endDate.py +24 -0
  36. tests/models/cycle/test_startDate.py +22 -0
  37. tests/models/faostat2018/product/test_price.py +40 -48
  38. tests/models/faostat2018/test_liveweightPerHead.py +106 -42
  39. tests/models/ipcc2019/test_organicCarbonPerHa.py +102 -39
  40. tests/models/schmidt2007/test_h2SToAirWasteTreatment.py +45 -0
  41. tests/models/utils/test_blank_node.py +71 -3
  42. hestia_earth/models/cycle/pre_checks/startDate.py +0 -52
  43. tests/models/cycle/pre_checks/test_startDate.py +0 -44
  44. {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/LICENSE +0 -0
  45. {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/WHEEL +0 -0
  46. {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ def _cache_results(results: list, collections: list, index: int):
34
34
  return cache_site_results(results[start:end], collections)
35
35
 
36
36
 
37
- def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors: list = [], years: list = []):
37
+ def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors: list = [], years: list = None):
38
38
  param_values = list(map(_VALUE_AS_PARAM.get(param_type), sites))
39
39
  # unique list
40
40
  param_values = list(set(param_values)) if param_type == ParamType.GADM_IDS else list({
@@ -66,11 +66,9 @@ def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors:
66
66
  } | ({CACHE_AREA_SIZE: area_size} if area_size is not None else {})
67
67
  return {
68
68
  **site,
69
- CACHE_KEY: {
70
- **cached_value(site),
71
- CACHE_YEARS_KEY: years,
72
- CACHE_GEOSPATIAL_KEY: cached_data
73
- }
69
+ CACHE_KEY: (
70
+ cached_value(site) | {CACHE_GEOSPATIAL_KEY: cached_data}
71
+ ) | ({CACHE_YEARS_KEY: years} if years else {})
74
72
  }
75
73
 
76
74
  return reduce(lambda prev, curr: prev + [_process_site(curr)], sites, [])
@@ -114,7 +112,7 @@ def _group_sites(sites: dict):
114
112
  }
115
113
 
116
114
 
117
- def run(sites: list, years: list, include_region: bool = False):
115
+ def run(sites: list, years: list = None, include_region: bool = False):
118
116
  """
119
117
  Run all queries at once for the list of provided Sites.
120
118
  Note: Earth Engine needs to be initiliased with `init_gee()` before running this function.
@@ -129,7 +127,7 @@ def run(sites: list, years: list, include_region: bool = False):
129
127
  Prefecth region IDs.
130
128
  This will cache region-level data and will make the request slower. Only use if needed.
131
129
  """
132
- rasters, vectors = list_collections(years, include_region=include_region)
130
+ rasters, vectors = list_collections(years, include_region)
133
131
 
134
132
  filtered_data = _group_sites(sites)
135
133
 
@@ -0,0 +1,86 @@
1
+ """
2
+ Milk Yield
3
+
4
+ This model gap-fills the practice "Milk yield per animal X (raw/FPCM)" (e.g. `Milk yield per cow (raw)`) when:
5
+ - the practice is added to the Cycle itself, and we can match it with the `term` of an Animal blank node;
6
+ - the Animal blank node Term has a lookup value of `kgDayMilkForFeedingOffspring`.
7
+ """
8
+ from hestia_earth.schema import TermTermType
9
+ from hestia_earth.utils.model import filter_list_term_type
10
+ from hestia_earth.utils.tools import non_empty_list, safe_parse_float
11
+
12
+ from hestia_earth.models.log import logShouldRun, logRequirements, log_blank_nodes_id
13
+ from hestia_earth.models.utils.term import get_lookup_value
14
+ from hestia_earth.models.utils.practice import _new_practice
15
+ from .. import MODEL
16
+
17
+ REQUIREMENTS = {
18
+ "Cycle": {
19
+ "animals": [{
20
+ "@type": "Animal",
21
+ "term.termType": "liveAnimal"
22
+ }],
23
+ "optional": {
24
+ "practices": [{
25
+ "@type": "Practice",
26
+ "term.termType": "animalManagement"
27
+ }]
28
+ }
29
+ }
30
+ }
31
+ RETURNS = {
32
+ "Animal": [{
33
+ "practices": [{
34
+ "@type": "Practice",
35
+ "term.termType": "animalManagement"
36
+ }]
37
+ }]
38
+ }
39
+ LOOKUPS = {
40
+ "liveAnimal": ["milkYieldPracticeTermIds", "kgDayMilkForFeedingOffspring"]
41
+ }
42
+
43
+ MODEL_KEY = 'milkYield'
44
+
45
+
46
+ def _default_practice(animal: dict, practice_term_id: str):
47
+ term = animal.get('term', {})
48
+ value = get_lookup_value(term, LOOKUPS['liveAnimal'][1], model=MODEL, model_key=MODEL_KEY)
49
+ return (_new_practice(practice_term_id) | {'value': [safe_parse_float(value)]}) if value else None
50
+
51
+
52
+ def _run(cycle: dict, animal: dict):
53
+ term = animal.get('term', {})
54
+ term_id = term.get('@id')
55
+ value = get_lookup_value(term, LOOKUPS['liveAnimal'][0], model=MODEL, model_key=MODEL_KEY)
56
+ practice_ids = non_empty_list((value or '').split(';'))
57
+ practices = non_empty_list(
58
+ [p for p in cycle.get('practices', []) if p.get('term', {}).get('@id') in practice_ids] or (
59
+ [_default_practice(animal, practice_ids[0])] if practice_ids else []
60
+ )
61
+ )
62
+
63
+ logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
64
+ practice_ids=log_blank_nodes_id(practices))
65
+
66
+ for practice in practices:
67
+ logShouldRun(cycle, MODEL, practice.get('term', {}).get('@id'), True, model_key=MODEL_KEY)
68
+
69
+ return {
70
+ **animal,
71
+ 'practices': animal.get('practices', []) + practices
72
+ } if practices else None
73
+
74
+
75
+ def _should_run(cycle: dict):
76
+ animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
77
+ has_animals = len(animals) > 0
78
+
79
+ should_run = all([has_animals])
80
+ logShouldRun(cycle, MODEL, None, should_run, model_key=MODEL_KEY)
81
+ return should_run, animals
82
+
83
+
84
+ def run(cycle: dict):
85
+ should_run, animals = _should_run(cycle)
86
+ return non_empty_list([_run(cycle, a) for a in animals]) if should_run else []
@@ -0,0 +1,50 @@
1
+ """
2
+ Start Date
3
+
4
+ This model updates the [Cycle endDate](https://hestia.earth/schema/Cycle#endDate) to be in the following format:
5
+ `YYYY-MM-DD`.
6
+ """
7
+ from hestia_earth.utils.date import is_in_days
8
+ from hestia_earth.utils.tools import non_empty_list
9
+
10
+ from hestia_earth.models.log import logRequirements, logShouldRun
11
+ from hestia_earth.models.utils import last_day_of_month
12
+ from . import MODEL
13
+
14
+ REQUIREMENTS = {
15
+ "Cycle": {
16
+ "endDate": ""
17
+ }
18
+ }
19
+ RETURNS = {
20
+ "The endDate as a string": ""
21
+ }
22
+ MODEL_KEY = 'endDate'
23
+
24
+
25
+ def _last_day(date: str):
26
+ last_day = last_day_of_month(date[0:4], date[5:7])
27
+ return str(last_day.day)
28
+
29
+
30
+ def _run(cycle: dict):
31
+ value = cycle.get('endDate')
32
+ month = '12' if len(value) == 4 else ''
33
+ day = '31' if len(value) == 4 else _last_day(value)
34
+ return '-'.join(non_empty_list([value, month, day]))
35
+
36
+
37
+ def _should_run(cycle: dict):
38
+ has_endDate = cycle.get('endDate') is not None
39
+ has_incorrect_format = has_endDate and not is_in_days(cycle.get('endDate'))
40
+
41
+ logRequirements(cycle, model=MODEL, key=MODEL_KEY,
42
+ has_endDate=has_endDate,
43
+ has_incorrect_format=has_incorrect_format)
44
+
45
+ should_run = all([has_endDate, has_incorrect_format])
46
+ logShouldRun(cycle, MODEL, None, should_run, key=MODEL_KEY)
47
+ return should_run
48
+
49
+
50
+ def run(cycle: dict): return _run(cycle) if _should_run(cycle) else None
@@ -34,7 +34,7 @@ RETURNS = {
34
34
  }
35
35
  LOOKUPS = {
36
36
  "inorganicFertiliser": [
37
- "mustIncludeId",
37
+ "complementaryTermIds",
38
38
  "nitrogenContent", "nitrogenContent-min", "nitrogenContent-max",
39
39
  "phosphateContentAsP2O5", "phosphateContentAsP2O5-min", "phosphateContentAsP2O5-max",
40
40
  "potassiumContentAsK2O", "potassiumContentAsK2O-min", "potassiumContentAsK2O-max"
@@ -75,7 +75,8 @@ def _input(term_id: str, value: float, min: float = None, max: float = None):
75
75
  return input
76
76
 
77
77
 
78
- def _include_term_ids(term_id: str): return non_empty_list((get_term_lookup(term_id, 'mustIncludeId') or '').split(';'))
78
+ def _include_term_ids(term_id: str):
79
+ return non_empty_list((get_term_lookup(term_id, LOOKUPS['inorganicFertiliser'][0]) or '').split(';'))
79
80
 
80
81
 
81
82
  def _run_input(cycle: dict, input: dict):
@@ -48,7 +48,7 @@ RETURNS = {
48
48
  }]
49
49
  }
50
50
  LOOKUPS = {
51
- "animalProduct": ["liveAnimalTermId", "milkYieldPracticeId"]
51
+ "animalProduct": ["liveAnimalTermId", "milkYieldPracticeTermId"]
52
52
  }
53
53
 
54
54
  MODEL_KEY = 'milkYield'
@@ -74,11 +74,16 @@ def practice(term_id: str, value: float, properties: list, sd: float = None, min
74
74
  return data
75
75
 
76
76
 
77
+ def _practice_id(term: dict):
78
+ value = get_lookup_value(term, LOOKUPS['animalProduct'][1], model=MODEL, model_key=MODEL_KEY)
79
+ return value.split(';')[0] if value else None
80
+
81
+
77
82
  def _run(cycle: dict, product: dict):
78
83
  cycleDuration = cycle.get('cycleDuration')
79
84
 
80
85
  term = product.get('term', {})
81
- practice_id = get_lookup_value(term, 'milkYieldPracticeId')
86
+ practice_id = _practice_id(term)
82
87
 
83
88
  live_animal_term_id = _get_liveAnimal_term_id(product, model_key=MODEL_KEY)
84
89
  live_animal_node = find_term_match(cycle.get('animals', []), live_animal_term_id)
@@ -114,7 +119,7 @@ def _should_run_product(cycle: dict, product: dict):
114
119
  live_animal_node = find_term_match(cycle.get('animals', []), live_animal_term_id)
115
120
  has_live_animal_node_value = live_animal_node.get('value', 0) > 0
116
121
 
117
- practice_id = get_lookup_value(term, 'milkYieldPracticeId', model=MODEL, model_key=MODEL_KEY)
122
+ practice_id = _practice_id(term)
118
123
  has_practice_id = any([
119
124
  find_term_match(cycle.get('practices', []), practice_id),
120
125
  find_term_match((live_animal_node or {}).get('practices', []), practice_id)
@@ -2,14 +2,13 @@ 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 site, startDate, cache_sources
5
+ from . import site, cache_sources
6
6
 
7
7
  CURRENT_DIR = dirname(abspath(__file__)) + '/'
8
8
  sys.path.append(CURRENT_DIR)
9
9
 
10
10
  MODELS = [
11
11
  site.run,
12
- startDate.run,
13
12
  cache_sources.run
14
13
  ]
15
14
 
@@ -9,7 +9,7 @@ from . import MODEL
9
9
 
10
10
  REQUIREMENTS = {
11
11
  "Cycle": {
12
- "cycleDuration": "365",
12
+ "cycleDuration": "> 0",
13
13
  "none": {
14
14
  "otherSites": ""
15
15
  }
@@ -0,0 +1,42 @@
1
+ """
2
+ Start Date
3
+
4
+ This model updates the [Cycle startDate](https://hestia.earth/schema/Cycle#startDate) to be in the following format:
5
+ `YYYY-MM-DD`.
6
+ """
7
+ from hestia_earth.utils.date import is_in_days
8
+ from hestia_earth.utils.tools import non_empty_list
9
+
10
+ from hestia_earth.models.log import logRequirements, logShouldRun
11
+ from . import MODEL
12
+
13
+ REQUIREMENTS = {
14
+ "Cycle": {
15
+ "startDate": ""
16
+ }
17
+ }
18
+ RETURNS = {
19
+ "The startDate as a string": ""
20
+ }
21
+ MODEL_KEY = 'startDate'
22
+
23
+
24
+ def _run(cycle: dict):
25
+ value = cycle.get('startDate')
26
+ return '-'.join(non_empty_list([value, '01' if len(value) == 4 else '', '01']))
27
+
28
+
29
+ def _should_run(cycle: dict):
30
+ has_startDate = cycle.get('startDate') is not None
31
+ has_incorrect_format = has_startDate and not is_in_days(cycle.get('startDate'))
32
+
33
+ logRequirements(cycle, model=MODEL, key=MODEL_KEY,
34
+ has_startDate=has_startDate,
35
+ has_incorrect_format=has_incorrect_format)
36
+
37
+ should_run = all([has_startDate, has_incorrect_format])
38
+ logShouldRun(cycle, MODEL, None, should_run, key=MODEL_KEY)
39
+ return should_run
40
+
41
+
42
+ def run(cycle: dict): return _run(cycle) if _should_run(cycle) else None
@@ -17,14 +17,17 @@ from . import MODEL
17
17
 
18
18
  REQUIREMENTS = {
19
19
  "Cycle": {
20
- "or": {
21
- "inputs": [{
20
+ "completeness.fertiliser": "True",
21
+ "inputs": [
22
+ {
22
23
  "@type": "Input",
23
24
  "value": "",
24
- "term.termType": ["inorganicFertiliser", "inorganicNitrogenFertiliserUnspecifiedKgN"]
25
- }],
26
- "completeness.fertiliser": "True"
27
- },
25
+ "term.termType": "inorganicFertiliser",
26
+ "optional": {
27
+ "properties": [{"@type": "Property", "value": "", "term.@id": "nitrogenContent"}]
28
+ }
29
+ }
30
+ ],
28
31
  "site": {
29
32
  "@type": "Site",
30
33
  "country": {"@type": "Term", "termType": "region"},
@@ -1,20 +1,25 @@
1
1
  from hestia_earth.schema import TermTermType
2
+ from hestia_earth.utils.api import download_hestia
3
+ from hestia_earth.utils.lookup import get_table_value, column_name, download_lookup, extract_grouped_data_closest_date
2
4
  from hestia_earth.utils.model import filter_list_term_type
3
- from hestia_earth.utils.tools import non_empty_list, safe_parse_date
5
+ from hestia_earth.utils.tools import non_empty_list, safe_parse_date, safe_parse_float
4
6
 
5
- from hestia_earth.models.log import logRequirements, logShouldRun
6
- from hestia_earth.models.utils import _filter_list_term_unit
7
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugMissingLookup
7
8
  from hestia_earth.models.utils.constant import Units
8
9
  from hestia_earth.models.utils.property import _new_property, node_has_no_property
10
+ from hestia_earth.models.utils.product import convert_product_to_unit
11
+ from hestia_earth.models.utils.animalProduct import FAO_LOOKUP_COLUMN, get_animalProduct_lookup_value
12
+ from .utils import get_liveAnimal_to_animalProduct_id
9
13
  from . import MODEL
10
- from .utils import product_equivalent_value
11
14
 
12
15
  REQUIREMENTS = {
13
16
  "Cycle": {
14
17
  "endDate": "",
15
- "products": [
16
- {"@type": "Product", "value": "", "term.termType": "animalProduct", "term.units": "kg liveweight"}
17
- ],
18
+ "products": [{
19
+ "@type": "Product",
20
+ "value": "",
21
+ "term.termType": ["animalProduct", "liveAnimal"]
22
+ }],
18
23
  "site": {
19
24
  "@type": "Site",
20
25
  "country": {"@type": "Term", "termType": "region"}
@@ -22,8 +27,9 @@ REQUIREMENTS = {
22
27
  }
23
28
  }
24
29
  LOOKUPS = {
25
- "region-animalProduct-animalProductGroupingFAO-productionQuantity": "production quantity",
26
- "region-animalProduct-animalProductGroupingFAO-head": "number of heads"
30
+ "liveAnimal": ["primaryMeatProductFaoProductionTermId"],
31
+ "animalProduct": ["animalProductGroupingFAOEquivalent", "animalProductGroupingFAO"],
32
+ "region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight": "use value from above"
27
33
  }
28
34
  RETURNS = {
29
35
  "Product": [{
@@ -34,6 +40,7 @@ RETURNS = {
34
40
  }]
35
41
  }
36
42
  TERM_ID = 'liveweightPerHead'
43
+ LOOKUP_WEIGHT = 'region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight.csv'
37
44
 
38
45
 
39
46
  def _property(value: float):
@@ -42,47 +49,76 @@ def _property(value: float):
42
49
  return prop
43
50
 
44
51
 
45
- def _should_run_product(cycle: dict, year: int, country: str):
46
- def exec(product: dict):
47
- product_id = product.get('term', {}).get('@id')
48
- value = product_equivalent_value(product, year, country)
49
- should_run = all([value])
50
- logShouldRun(cycle, MODEL, product_id, should_run, property=TERM_ID)
51
- return should_run, product, value
52
- return exec
52
+ def _product_value(product: dict, year: int, country_id: str):
53
+ product_id = product.get('term', {}).get('@id')
54
+ groupingFAO = get_animalProduct_lookup_value(MODEL, product_id, FAO_LOOKUP_COLUMN)
53
55
 
56
+ lookup = download_lookup(LOOKUP_WEIGHT)
57
+ data = get_table_value(lookup, 'termid', country_id, column_name(groupingFAO))
58
+ debugMissingLookup(LOOKUP_WEIGHT, 'termid', country_id, groupingFAO, data, model=MODEL, term=TERM_ID)
59
+ average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), None)
60
+ # average_carcass_weight is in hg, divide by 10 to go back to kg
61
+ kg_carcass_weight = average_carcass_weight / 10 if average_carcass_weight else None
54
62
 
55
- def _run(products: list):
56
- def run_product(values: tuple):
57
- product, value = values
58
- prop = _property(value)
59
- return {**product, 'properties': product.get('properties', []) + [prop]} if prop else None
63
+ kg_liveweight = convert_product_to_unit({
64
+ **product,
65
+ 'value': [kg_carcass_weight]
66
+ }, Units.KG_LIVEWEIGHT) if kg_carcass_weight else None
60
67
 
61
- return non_empty_list(map(run_product, products))
68
+ return kg_liveweight, groupingFAO
62
69
 
63
70
 
64
- def _should_run(cycle: dict):
65
- products = filter_list_term_type(cycle.get('products', []), TermTermType.ANIMALPRODUCT)
66
- products = _filter_list_term_unit(products, Units.KG_LIVEWEIGHT)
67
- products = list(filter(node_has_no_property(TERM_ID), products))
68
- has_kg_liveweight_products = len(products) > 0
71
+ def _should_run_liveAnimal(product: dict):
72
+ return product.get('term', {}).get('termType') == TermTermType.LIVEANIMAL.value
69
73
 
70
- end_date = safe_parse_date(cycle.get('endDate'))
71
- year = end_date.year if end_date else None
72
- country = cycle.get('site', {}).get('country', {}).get('@id')
73
74
 
74
- logRequirements(cycle, model=MODEL, term=TERM_ID,
75
- has_kg_liveweight_products=has_kg_liveweight_products,
75
+ def _run_liveAnimal(cycle: dict, product: dict, year: int, country_id: str):
76
+ # find the animalProduct to get the average carcass weight
77
+ product_id = product.get('term', {}).get('@id')
78
+ animal_product_id = get_liveAnimal_to_animalProduct_id(product_id, LOOKUPS['liveAnimal'][0], term=TERM_ID)
79
+
80
+ animal_product_term = download_hestia(animal_product_id)
81
+ kg_liveweight, groupingFAO = _product_value({**product, 'term': animal_product_term}, year, country_id)
82
+
83
+ logRequirements(cycle, model=MODEL, term=product_id, property=TERM_ID,
84
+ animal_product_id=animal_product_id,
85
+ country_id=country_id,
76
86
  year=year,
77
- country=country)
87
+ kg_liveweight=kg_liveweight,
88
+ groupingFAO=groupingFAO)
78
89
 
79
- should_run = all([has_kg_liveweight_products, year, country])
80
- logShouldRun(cycle, MODEL, TERM_ID, should_run)
81
- return should_run, products, year, country
90
+ should_run = all([kg_liveweight])
91
+ logShouldRun(cycle, MODEL, product_id, should_run, property=TERM_ID)
92
+
93
+ return {**product, 'properties': product.get('properties', []) + [_property(kg_liveweight)]} if should_run else None
94
+
95
+
96
+ def _run_animalProduct(cycle: dict, product: dict, year: int, country_id: str):
97
+ product_id = product.get('term', {}).get('@id')
98
+ kg_liveweight, groupingFAO = _product_value(product, year, country_id)
99
+
100
+ logRequirements(cycle, model=MODEL, term=product_id, property=TERM_ID,
101
+ country_id=country_id,
102
+ year=year,
103
+ kg_liveweight=kg_liveweight,
104
+ groupingFAO=groupingFAO)
105
+
106
+ should_run = all([kg_liveweight])
107
+ logShouldRun(cycle, MODEL, product_id, should_run, property=TERM_ID)
108
+
109
+ return {**product, 'properties': product.get('properties', []) + [_property(kg_liveweight)]} if should_run else None
82
110
 
83
111
 
84
112
  def run(cycle: dict):
85
- should_run, products, year, country = _should_run(cycle)
86
- products = list(map(_should_run_product(cycle, year, country), products)) if should_run else []
87
- products = [(product, value) for (should_run, product, value) in products if should_run]
88
- return _run(products) if should_run else []
113
+ country_id = cycle.get('site', {}).get('country', {}).get('@id')
114
+ end_date = safe_parse_date(cycle.get('endDate'))
115
+ year = end_date.year if end_date else None
116
+
117
+ products = filter_list_term_type(cycle.get('products', []), [TermTermType.ANIMALPRODUCT, TermTermType.LIVEANIMAL])
118
+ products = list(filter(node_has_no_property(TERM_ID), products))
119
+
120
+ return non_empty_list([
121
+ (
122
+ (_run_liveAnimal if _should_run_liveAnimal(p) else _run_animalProduct)(cycle, p, year, country_id)
123
+ ) for p in products
124
+ ]) if country_id else []