hestia-earth-models 0.64.4__py3-none-any.whl → 0.64.5__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.
- hestia_earth/models/blonkConsultants2016/ch4ToAirNaturalVegetationBurning.py +5 -9
- hestia_earth/models/blonkConsultants2016/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +5 -9
- hestia_earth/models/blonkConsultants2016/n2OToAirNaturalVegetationBurningDirect.py +6 -13
- hestia_earth/models/cycle/animal/input/properties.py +6 -0
- hestia_earth/models/cycle/completeness/soilAmendment.py +3 -2
- hestia_earth/models/cycle/concentrateFeed.py +10 -4
- hestia_earth/models/cycle/input/properties.py +6 -0
- hestia_earth/models/cycle/liveAnimal.py +2 -2
- hestia_earth/models/cycle/milkYield.py +3 -3
- hestia_earth/models/cycle/otherSitesArea.py +59 -0
- hestia_earth/models/cycle/otherSitesUnusedDuration.py +9 -8
- hestia_earth/models/cycle/pastureSystem.py +3 -2
- hestia_earth/models/cycle/product/properties.py +6 -0
- hestia_earth/models/cycle/siteArea.py +83 -0
- hestia_earth/models/cycle/stockingDensityAnimalHousingAverage.py +28 -16
- hestia_earth/models/cycle/utils.py +1 -1
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +128 -0
- hestia_earth/models/environmentalFootprintV3/utils.py +17 -0
- hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +17 -6
- hestia_earth/models/ipcc2006/n2OToAirOrganicSoilCultivationDirect.py +17 -6
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +904 -0
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +70 -618
- hestia_earth/models/mocking/search-results.json +395 -323
- hestia_earth/models/pooreNemecek2018/saplings.py +10 -7
- hestia_earth/models/site/management.py +18 -14
- hestia_earth/models/utils/__init__.py +38 -0
- hestia_earth/models/utils/array_builders.py +63 -52
- hestia_earth/models/utils/blank_node.py +137 -82
- hestia_earth/models/utils/descriptive_stats.py +3 -239
- hestia_earth/models/utils/feedipedia.py +15 -2
- hestia_earth/models/utils/landCover.py +9 -0
- hestia_earth/models/utils/lookup.py +13 -2
- hestia_earth/models/utils/measurement.py +3 -28
- hestia_earth/models/utils/stats.py +429 -0
- hestia_earth/models/utils/term.py +15 -3
- hestia_earth/models/utils/time_series.py +90 -0
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/RECORD +62 -48
- tests/models/blonkConsultants2016/test_ch4ToAirNaturalVegetationBurning.py +2 -2
- tests/models/blonkConsultants2016/test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +2 -2
- tests/models/blonkConsultants2016/test_n2OToAirNaturalVegetationBurningDirect.py +2 -2
- tests/models/cycle/completeness/test_soilAmendment.py +1 -1
- tests/models/cycle/test_liveAnimal.py +1 -1
- tests/models/cycle/test_milkYield.py +1 -1
- tests/models/cycle/test_otherSitesArea.py +68 -0
- tests/models/cycle/test_siteArea.py +51 -0
- tests/models/cycle/test_stockingDensityAnimalHousingAverage.py +2 -2
- tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +136 -0
- tests/models/ipcc2019/test_co2ToAirCarbonStockChange_utils.py +50 -0
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +1 -39
- tests/models/pooreNemecek2018/test_saplings.py +1 -1
- tests/models/site/test_management.py +3 -153
- tests/models/utils/test_array_builders.py +67 -6
- tests/models/utils/test_blank_node.py +191 -7
- tests/models/utils/test_descriptive_stats.py +2 -86
- tests/models/utils/test_measurement.py +1 -22
- tests/models/utils/test_stats.py +186 -0
- tests/models/utils/test_time_series.py +88 -0
- {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, CycleFunctionalUnit
|
|
2
2
|
|
|
3
3
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
@@ -8,16 +8,10 @@ from . import MODEL
|
|
|
8
8
|
|
|
9
9
|
REQUIREMENTS = {
|
|
10
10
|
"Cycle": {
|
|
11
|
+
"functionalUnit": "1 ha",
|
|
11
12
|
"or": [
|
|
12
13
|
{
|
|
13
|
-
"@doc": "if the [cycle.functionalUnit](https://hestia.earth/schema/Cycle#functionalUnit) = 1 ha, additional properties are required", # noqa: E501
|
|
14
14
|
"cycleDuration": "",
|
|
15
|
-
"products": [{
|
|
16
|
-
"@type": "Product",
|
|
17
|
-
"primary": "True",
|
|
18
|
-
"value": "> 0",
|
|
19
|
-
"economicValueShare": "> 0"
|
|
20
|
-
}],
|
|
21
15
|
"practices": [{"@type": "Practice", "value": "", "term.@id": "longFallowRatio"}]
|
|
22
16
|
},
|
|
23
17
|
{
|
|
@@ -65,14 +59,16 @@ def _run(land_occupation: float, ch4_forest_biomass_burning: float):
|
|
|
65
59
|
|
|
66
60
|
|
|
67
61
|
def _should_run(cycle: dict):
|
|
62
|
+
is_1_ha_functional_unit = cycle.get('functionalUnit') == CycleFunctionalUnit._1_HA.value
|
|
68
63
|
land_occupation = land_occupation_per_ha(MODEL, TERM_ID, cycle)
|
|
69
64
|
ch4_forest_biomass_burning = get_emission_factor(TERM_ID, cycle, 'ch4forestBiomassBurning')
|
|
70
65
|
|
|
71
66
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
67
|
+
is_1_ha_functional_unit=is_1_ha_functional_unit,
|
|
72
68
|
land_occupation=land_occupation,
|
|
73
69
|
ch4_forest_biomass_burning=ch4_forest_biomass_burning)
|
|
74
70
|
|
|
75
|
-
should_run = all([land_occupation, ch4_forest_biomass_burning is not None])
|
|
71
|
+
should_run = all([is_1_ha_functional_unit, land_occupation, ch4_forest_biomass_burning is not None])
|
|
76
72
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
|
77
73
|
return should_run, land_occupation, ch4_forest_biomass_burning
|
|
78
74
|
|
hestia_earth/models/blonkConsultants2016/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, CycleFunctionalUnit
|
|
2
2
|
|
|
3
3
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
@@ -8,16 +8,10 @@ from . import MODEL
|
|
|
8
8
|
|
|
9
9
|
REQUIREMENTS = {
|
|
10
10
|
"Cycle": {
|
|
11
|
+
"functionalUnit": "1 ha",
|
|
11
12
|
"or": [
|
|
12
13
|
{
|
|
13
|
-
"@doc": "if the [cycle.functionalUnit](https://hestia.earth/schema/Cycle#functionalUnit) = 1 ha, additional properties are required", # noqa: E501
|
|
14
14
|
"cycleDuration": "",
|
|
15
|
-
"products": [{
|
|
16
|
-
"@type": "Product",
|
|
17
|
-
"primary": "True",
|
|
18
|
-
"value": "> 0",
|
|
19
|
-
"economicValueShare": "> 0"
|
|
20
|
-
}],
|
|
21
15
|
"practices": [{"@type": "Practice", "value": "", "term.@id": "longFallowRatio"}]
|
|
22
16
|
},
|
|
23
17
|
{
|
|
@@ -65,14 +59,16 @@ def _run(land_occupation: float, co2_land_use_change: float):
|
|
|
65
59
|
|
|
66
60
|
|
|
67
61
|
def _should_run(cycle: dict):
|
|
62
|
+
is_1_ha_functional_unit = cycle.get('functionalUnit') == CycleFunctionalUnit._1_HA.value
|
|
68
63
|
land_occupation = land_occupation_per_ha(MODEL, TERM_ID, cycle)
|
|
69
64
|
co2_land_use_change = get_emission_factor(TERM_ID, cycle, 'co2LandUseChange')
|
|
70
65
|
|
|
71
66
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
67
|
+
is_1_ha_functional_unit=is_1_ha_functional_unit,
|
|
72
68
|
land_occupation=land_occupation,
|
|
73
69
|
co2_land_use_change=co2_land_use_change)
|
|
74
70
|
|
|
75
|
-
should_run = all([land_occupation, co2_land_use_change is not None])
|
|
71
|
+
should_run = all([is_1_ha_functional_unit, land_occupation, co2_land_use_change is not None])
|
|
76
72
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
|
77
73
|
return should_run, land_occupation, co2_land_use_change
|
|
78
74
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from hestia_earth.schema import EmissionMethodTier
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, CycleFunctionalUnit
|
|
2
2
|
|
|
3
3
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
@@ -8,20 +8,11 @@ from . import MODEL
|
|
|
8
8
|
|
|
9
9
|
REQUIREMENTS = {
|
|
10
10
|
"Cycle": {
|
|
11
|
+
"functionalUnit": "1 ha",
|
|
11
12
|
"or": [
|
|
12
13
|
{
|
|
13
|
-
"@doc": "if the [cycle.functionalUnit](https://hestia.earth/schema/Cycle#functionalUnit) = 1 ha, additional properties are required", # noqa: E501
|
|
14
14
|
"cycleDuration": "",
|
|
15
|
-
"
|
|
16
|
-
"@type": "Product",
|
|
17
|
-
"primary": "True",
|
|
18
|
-
"value": "> 0",
|
|
19
|
-
"economicValueShare": "> 0"
|
|
20
|
-
}],
|
|
21
|
-
"site": {
|
|
22
|
-
"@type": "Site",
|
|
23
|
-
"practices": [{"@type": "Practice", "value": "", "term.@id": "longFallowRatio"}]
|
|
24
|
-
}
|
|
15
|
+
"practices": [{"@type": "Practice", "value": "", "term.@id": "longFallowRatio"}]
|
|
25
16
|
},
|
|
26
17
|
{
|
|
27
18
|
"@doc": "for plantations, additional properties are required",
|
|
@@ -68,14 +59,16 @@ def _run(land_occupation: float, n2o_forest_biomass_burning: float):
|
|
|
68
59
|
|
|
69
60
|
|
|
70
61
|
def _should_run(cycle: dict):
|
|
62
|
+
is_1_ha_functional_unit = cycle.get('functionalUnit') == CycleFunctionalUnit._1_HA.value
|
|
71
63
|
land_occupation = land_occupation_per_ha(MODEL, TERM_ID, cycle)
|
|
72
64
|
n2o_forest_biomass_burning = get_emission_factor(TERM_ID, cycle, 'n2oforestBiomassBurning')
|
|
73
65
|
|
|
74
66
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
67
|
+
is_1_ha_functional_unit=is_1_ha_functional_unit,
|
|
75
68
|
land_occupation=land_occupation,
|
|
76
69
|
n2o_forest_biomass_burning=n2o_forest_biomass_burning)
|
|
77
70
|
|
|
78
|
-
should_run = all([land_occupation, n2o_forest_biomass_burning is not None])
|
|
71
|
+
should_run = all([is_1_ha_functional_unit, land_occupation, n2o_forest_biomass_burning is not None])
|
|
79
72
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
|
80
73
|
return should_run, land_occupation, n2o_forest_biomass_burning
|
|
81
74
|
|
|
@@ -6,7 +6,8 @@ This model checks if we have the requirements below and updates the
|
|
|
6
6
|
"""
|
|
7
7
|
from hestia_earth.models.log import logRequirements
|
|
8
8
|
from hestia_earth.models.utils import is_from_model
|
|
9
|
-
from hestia_earth.models.utils.measurement import
|
|
9
|
+
from hestia_earth.models.utils.measurement import measurement_value
|
|
10
|
+
from hestia_earth.models.utils.blank_node import most_relevant_blank_node_by_id
|
|
10
11
|
from . import MODEL
|
|
11
12
|
|
|
12
13
|
REQUIREMENTS = {
|
|
@@ -30,7 +31,7 @@ MODEL_KEY = 'soilAmendment'
|
|
|
30
31
|
def run(cycle: dict):
|
|
31
32
|
end_date = cycle.get('endDate')
|
|
32
33
|
measurements = cycle.get('site', {}).get('measurements', [])
|
|
33
|
-
soilPh_measurement =
|
|
34
|
+
soilPh_measurement = most_relevant_blank_node_by_id(measurements, 'soilPh', end_date)
|
|
34
35
|
soilPh = measurement_value(soilPh_measurement)
|
|
35
36
|
|
|
36
37
|
soilPh_added = is_from_model(soilPh_measurement)
|
|
@@ -9,6 +9,7 @@ from hestia_earth.utils.model import find_primary_product
|
|
|
9
9
|
from hestia_earth.utils.tools import list_sum, non_empty_list, flatten
|
|
10
10
|
|
|
11
11
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
12
|
+
from hestia_earth.models.utils.blank_node import merge_blank_nodes
|
|
12
13
|
from hestia_earth.models.utils.property import _new_property, get_node_property_value, get_property_lookup_value
|
|
13
14
|
from hestia_earth.models.utils.term import get_digestible_energy_terms, get_energy_digestibility_terms
|
|
14
15
|
from . import MODEL
|
|
@@ -41,6 +42,7 @@ LOOKUPS = {
|
|
|
41
42
|
"property": "commonToSupplementInAnimalFeed"
|
|
42
43
|
}
|
|
43
44
|
TERM_ID = 'concentrateFeedBlend,concentrateFeedUnspecified,feedMix'
|
|
45
|
+
FIRST_TERM_ID = TERM_ID.split(',')[0]
|
|
44
46
|
INPUT_TERM_TYPES = [
|
|
45
47
|
TermTermType.CROP.value,
|
|
46
48
|
TermTermType.FORAGE.value,
|
|
@@ -88,7 +90,7 @@ def _calculate_value(cycle: dict, product: dict, inputs: list, property_id: str,
|
|
|
88
90
|
def _calculate_default_value(cycle: dict, product: dict, inputs: list, property_id: str):
|
|
89
91
|
values = [(
|
|
90
92
|
i.get('term', {}).get('@id'),
|
|
91
|
-
get_node_property_value(MODEL, i, property_id, handle_percents=False, term=
|
|
93
|
+
get_node_property_value(MODEL, i, property_id, handle_percents=False, term=FIRST_TERM_ID),
|
|
92
94
|
list_sum(i.get('value', []))
|
|
93
95
|
) for i in inputs]
|
|
94
96
|
return _calculate_value(cycle, product, inputs, property_id, values)
|
|
@@ -97,8 +99,9 @@ def _calculate_default_value(cycle: dict, product: dict, inputs: list, property_
|
|
|
97
99
|
def _calculate_N_value(cycle: dict, product: dict, inputs: list, property_id: str):
|
|
98
100
|
values = [(
|
|
99
101
|
i.get('term', {}).get('@id'),
|
|
100
|
-
get_node_property_value(MODEL, i, property_id, handle_percents=False, term=
|
|
101
|
-
get_node_property_value(
|
|
102
|
+
get_node_property_value(MODEL, i, property_id, handle_percents=False, term=FIRST_TERM_ID) or
|
|
103
|
+
get_node_property_value(
|
|
104
|
+
MODEL, i, 'crudeProteinContent', default=0, handle_percents=False, term=FIRST_TERM_ID) * 0.16,
|
|
102
105
|
list_sum(i.get('value', []))
|
|
103
106
|
) for i in inputs]
|
|
104
107
|
return _calculate_value(cycle, product, inputs, property_id, values)
|
|
@@ -136,7 +139,10 @@ def _run_property(cycle: dict, product: dict, inputs: list):
|
|
|
136
139
|
|
|
137
140
|
def _run(cycle: dict, product: dict, inputs: list):
|
|
138
141
|
properties = non_empty_list(flatten(map(_run_property(cycle, product, inputs), PROPERTY_TO_VALUE.items())))
|
|
139
|
-
return [
|
|
142
|
+
return [product | {
|
|
143
|
+
# keep the original values, so merge orignal in new values
|
|
144
|
+
'properties': merge_blank_nodes(properties, product.get('properties', []))
|
|
145
|
+
}] if len(properties) > 0 else []
|
|
140
146
|
|
|
141
147
|
|
|
142
148
|
def _should_run(cycle: dict):
|
|
@@ -10,7 +10,7 @@ from hestia_earth.utils.tools import list_sum, safe_parse_float
|
|
|
10
10
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
11
11
|
from hestia_earth.models.utils.product import _new_product
|
|
12
12
|
from hestia_earth.models.utils.site import valid_site_type
|
|
13
|
-
from .utils import
|
|
13
|
+
from .utils import get_liveAnimal_term_id
|
|
14
14
|
from . import MODEL
|
|
15
15
|
|
|
16
16
|
REQUIREMENTS = {
|
|
@@ -74,7 +74,7 @@ def _should_run(cycle: dict):
|
|
|
74
74
|
propertyPerHead_value = safe_parse_float(propertyPerHead.get('value'), None)
|
|
75
75
|
|
|
76
76
|
# make sure the `liveAnimal` Term is not already present as a Product or Input
|
|
77
|
-
term_id =
|
|
77
|
+
term_id = get_liveAnimal_term_id(product, model_key=MODEL_KEY)
|
|
78
78
|
has_liveAnimal_product = find_term_match(cycle.get('products', []), term_id, None) is not None
|
|
79
79
|
has_liveAnimal_input = find_term_match(cycle.get('products', []), term_id, None) is not None
|
|
80
80
|
|
|
@@ -16,7 +16,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun, log_blank_nod
|
|
|
16
16
|
from hestia_earth.models.utils.practice import _new_practice
|
|
17
17
|
from hestia_earth.models.utils.site import valid_site_type
|
|
18
18
|
from hestia_earth.models.utils.term import get_lookup_value
|
|
19
|
-
from .utils import
|
|
19
|
+
from .utils import get_liveAnimal_term_id
|
|
20
20
|
from . import MODEL
|
|
21
21
|
|
|
22
22
|
REQUIREMENTS = {
|
|
@@ -85,7 +85,7 @@ def _run(cycle: dict, product: dict):
|
|
|
85
85
|
term = product.get('term', {})
|
|
86
86
|
practice_id = _practice_id(term)
|
|
87
87
|
|
|
88
|
-
live_animal_term_id =
|
|
88
|
+
live_animal_term_id = get_liveAnimal_term_id(product, model_key=MODEL_KEY)
|
|
89
89
|
live_animal_node = find_term_match(cycle.get('animals', []), live_animal_term_id)
|
|
90
90
|
|
|
91
91
|
value = list_sum(product.get('value')) / cycleDuration / live_animal_node.get('value')
|
|
@@ -115,7 +115,7 @@ def _should_run_product(cycle: dict, product: dict):
|
|
|
115
115
|
|
|
116
116
|
has_product_value = list_sum(product.get('value', [])) > 0
|
|
117
117
|
|
|
118
|
-
live_animal_term_id =
|
|
118
|
+
live_animal_term_id = get_liveAnimal_term_id(product, model_key=MODEL_KEY)
|
|
119
119
|
live_animal_node = find_term_match(cycle.get('animals', []), live_animal_term_id)
|
|
120
120
|
has_live_animal_node_value = live_animal_node.get('value', 0) > 0
|
|
121
121
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Other Sites Area
|
|
3
|
+
|
|
4
|
+
For animal production cycles, use the `stockingDensityAnimalHousingAverage` to calculate the average area required
|
|
5
|
+
for all animals.
|
|
6
|
+
"""
|
|
7
|
+
from hestia_earth.schema import SiteSiteType
|
|
8
|
+
|
|
9
|
+
from .siteArea import _is_site_valid, _should_run as _should_run_site, _run
|
|
10
|
+
|
|
11
|
+
REQUIREMENTS = {
|
|
12
|
+
"Cycle": {
|
|
13
|
+
"otherSites": [{
|
|
14
|
+
"@type": "Site",
|
|
15
|
+
"siteType": "animal housing"
|
|
16
|
+
}],
|
|
17
|
+
"none": {
|
|
18
|
+
"site": {
|
|
19
|
+
"@type": "Site",
|
|
20
|
+
"siteType": "animal housing"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"animals": [{
|
|
24
|
+
"@type": "Animal",
|
|
25
|
+
"term.termType": "liveAnimal",
|
|
26
|
+
"value": "> 0"
|
|
27
|
+
}],
|
|
28
|
+
"practices": [{
|
|
29
|
+
"@type": "Practice",
|
|
30
|
+
"term.@id": "stockingDensityAnimalHousingAverage"
|
|
31
|
+
}]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
RETURNS = {
|
|
35
|
+
"The otherSitesArea as an array of number": ""
|
|
36
|
+
}
|
|
37
|
+
MODEL_KEY = 'otherSitesArea'
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _should_run(cycle: dict):
|
|
41
|
+
other_sites_valid = list(filter(
|
|
42
|
+
lambda site: site.get('siteType') == SiteSiteType.ANIMAL_HOUSING.value,
|
|
43
|
+
cycle.get('otherSites', [])
|
|
44
|
+
))
|
|
45
|
+
|
|
46
|
+
should_run = all([
|
|
47
|
+
not _is_site_valid(cycle.get('site', {})),
|
|
48
|
+
len(other_sites_valid) == 1
|
|
49
|
+
]) and _should_run_site(cycle, other_sites_valid[0], key=MODEL_KEY)
|
|
50
|
+
return should_run
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def run(cycle: dict):
|
|
54
|
+
other_sites = cycle.get('otherSites', [])
|
|
55
|
+
other_sites_area = cycle.get('otherSitesArea')
|
|
56
|
+
return [
|
|
57
|
+
_run(cycle) if _is_site_valid(site) else other_sites_area[index] if other_sites_area else None
|
|
58
|
+
for index, site in enumerate(other_sites)
|
|
59
|
+
] if _should_run(cycle) else []
|
|
@@ -51,6 +51,13 @@ def _find_site_practice(practices: list, site_id: str):
|
|
|
51
51
|
).get('value'), None)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
def _is_valid(data: dict): return all([
|
|
55
|
+
data.get('valid-site'),
|
|
56
|
+
data.get(_PRACTICE_TERM_ID) is not None,
|
|
57
|
+
data.get('site-duration') is not None
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
|
|
54
61
|
def _should_run(cycle: dict):
|
|
55
62
|
otherSitesDuration = cycle.get('otherSitesDuration', [])
|
|
56
63
|
practices = cycle.get('practices', [])
|
|
@@ -66,13 +73,7 @@ def _should_run(cycle: dict):
|
|
|
66
73
|
for index, site in enumerate(cycle.get('otherSites', []))
|
|
67
74
|
]
|
|
68
75
|
|
|
69
|
-
has_valid_sites = any(
|
|
70
|
-
all([
|
|
71
|
-
data.get('valid-site'),
|
|
72
|
-
data.get(_PRACTICE_TERM_ID) is not None,
|
|
73
|
-
(data.get('site-duration') or 0) >= 0
|
|
74
|
-
]) for data in site_data
|
|
75
|
-
])
|
|
76
|
+
has_valid_sites = any(map(_is_valid, site_data))
|
|
76
77
|
|
|
77
78
|
logRequirements(cycle, model=MODEL, key=MODEL_KEY,
|
|
78
79
|
has_valid_sites=has_valid_sites,
|
|
@@ -86,6 +87,6 @@ def _should_run(cycle: dict):
|
|
|
86
87
|
def run(cycle: dict):
|
|
87
88
|
should_run, site_data = _should_run(cycle)
|
|
88
89
|
return [
|
|
89
|
-
_run(data.get('site-duration'), data.get(_PRACTICE_TERM_ID)) if data
|
|
90
|
+
_run(data.get('site-duration'), data.get(_PRACTICE_TERM_ID)) if _is_valid(data) else None
|
|
90
91
|
for data in site_data
|
|
91
92
|
] if should_run else []
|
|
@@ -10,7 +10,8 @@ from hestia_earth.utils.model import find_primary_product, find_term_match
|
|
|
10
10
|
from hestia_earth.models.log import logRequirements, logShouldRun, debugValues
|
|
11
11
|
from hestia_earth.models.utils.practice import _new_practice
|
|
12
12
|
from hestia_earth.models.utils.site import valid_site_type
|
|
13
|
-
from hestia_earth.models.utils.measurement import
|
|
13
|
+
from hestia_earth.models.utils.measurement import measurement_value
|
|
14
|
+
from hestia_earth.models.utils.blank_node import most_relevant_blank_node_by_id
|
|
14
15
|
from hestia_earth.models.utils.term import get_pasture_system_terms
|
|
15
16
|
from . import MODEL
|
|
16
17
|
|
|
@@ -46,7 +47,7 @@ def _practice(term_id: str):
|
|
|
46
47
|
def _run(cycle: dict):
|
|
47
48
|
end_date = cycle.get('endDate')
|
|
48
49
|
measurements = cycle.get('site', {}).get('measurements', [])
|
|
49
|
-
slope = measurement_value(
|
|
50
|
+
slope = measurement_value(most_relevant_blank_node_by_id(measurements, 'slope', end_date))
|
|
50
51
|
term_id = 'confinedPastureSystem' if slope <= 2.5 else 'hillyPastureSystem'
|
|
51
52
|
|
|
52
53
|
debugValues(cycle, model=MODEL, term=term_id,
|
|
@@ -28,6 +28,12 @@ RETURNS = {
|
|
|
28
28
|
}]
|
|
29
29
|
}]
|
|
30
30
|
}
|
|
31
|
+
LOOKUPS = {
|
|
32
|
+
"crop-property": "dryMatter",
|
|
33
|
+
"forage-property": "dryMatter",
|
|
34
|
+
"processedFoor-property": "dryMatter",
|
|
35
|
+
"property": "feedipediaConversionEnum"
|
|
36
|
+
}
|
|
31
37
|
MODEL_KEY = 'properties'
|
|
32
38
|
DRY_MATTER_TERM_ID = 'dryMatter'
|
|
33
39
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Site Area
|
|
3
|
+
|
|
4
|
+
For animal production cycles, use the `stockingDensityAnimalHousingAverage` to calculate the average area required
|
|
5
|
+
for all animals.
|
|
6
|
+
"""
|
|
7
|
+
from hestia_earth.schema import TermTermType, SiteSiteType
|
|
8
|
+
from hestia_earth.utils.model import filter_list_term_type, find_term_match
|
|
9
|
+
from hestia_earth.utils.tools import list_sum
|
|
10
|
+
|
|
11
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
12
|
+
from . import MODEL
|
|
13
|
+
|
|
14
|
+
REQUIREMENTS = {
|
|
15
|
+
"Cycle": {
|
|
16
|
+
"site": {
|
|
17
|
+
"@type": "Site",
|
|
18
|
+
"siteType": "animal housing"
|
|
19
|
+
},
|
|
20
|
+
"none": {
|
|
21
|
+
"otherSites": [{
|
|
22
|
+
"@type": "Site",
|
|
23
|
+
"siteType": "animal housing"
|
|
24
|
+
}]
|
|
25
|
+
},
|
|
26
|
+
"animals": [{
|
|
27
|
+
"@type": "Animal",
|
|
28
|
+
"term.termType": "liveAnimal",
|
|
29
|
+
"value": "> 0"
|
|
30
|
+
}],
|
|
31
|
+
"practices": [{
|
|
32
|
+
"@type": "Practice",
|
|
33
|
+
"term.@id": "stockingDensityAnimalHousingAverage",
|
|
34
|
+
"value": "> 0"
|
|
35
|
+
}]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
RETURNS = {
|
|
39
|
+
"The siteArea as a number": ""
|
|
40
|
+
}
|
|
41
|
+
MODEL_KEY = 'siteArea'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _is_site_valid(site: dict): return site.get('siteType') == SiteSiteType.ANIMAL_HOUSING.value
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _run(cycle: dict):
|
|
48
|
+
animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
|
|
49
|
+
stocking_density = find_term_match(
|
|
50
|
+
cycle.get('practices', []), 'stockingDensityAnimalHousingAverage', {}).get('value', [])
|
|
51
|
+
return round(list_sum([a.get('value') for a in animals]) / list_sum(stocking_density), 7)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _should_run(cycle: dict, site: dict, key=MODEL_KEY):
|
|
55
|
+
site_type_valid = _is_site_valid(site)
|
|
56
|
+
animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
|
|
57
|
+
values = [{
|
|
58
|
+
'id': p.get('term', {}).get('@id'),
|
|
59
|
+
'value': p.get('value')
|
|
60
|
+
} for p in animals]
|
|
61
|
+
has_animals = bool(animals)
|
|
62
|
+
stocking_density = list_sum(
|
|
63
|
+
find_term_match(cycle.get('practices', []), 'stockingDensityAnimalHousingAverage', {}).get('value', [-1])
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
logRequirements(cycle, model=MODEL, key=key,
|
|
67
|
+
site_type_valid=site_type_valid,
|
|
68
|
+
values=log_as_table(values),
|
|
69
|
+
stocking_density=stocking_density)
|
|
70
|
+
|
|
71
|
+
should_run = all([
|
|
72
|
+
site_type_valid,
|
|
73
|
+
has_animals,
|
|
74
|
+
(stocking_density or 0) > 0
|
|
75
|
+
])
|
|
76
|
+
logShouldRun(cycle, MODEL, None, should_run, key=key)
|
|
77
|
+
return should_run
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def run(cycle: dict):
|
|
81
|
+
site = cycle.get('site')
|
|
82
|
+
has_other_sites_valid = any(map(_is_site_valid, cycle.get('otherSites', [])))
|
|
83
|
+
return _run(cycle) if _should_run(cycle, site, key=MODEL_KEY) and not has_other_sites_valid else None
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
from hestia_earth.schema import TermTermType
|
|
2
|
-
from hestia_earth.utils.model import
|
|
2
|
+
from hestia_earth.utils.model import filter_list_term_type
|
|
3
3
|
|
|
4
|
-
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
5
|
+
from hestia_earth.models.utils import weighted_average
|
|
5
6
|
from hestia_earth.models.utils.blank_node import get_lookup_value
|
|
6
7
|
from hestia_earth.models.utils.practice import _new_practice
|
|
7
8
|
from . import MODEL
|
|
8
9
|
|
|
9
10
|
REQUIREMENTS = {
|
|
10
11
|
"Cycle": {
|
|
11
|
-
"
|
|
12
|
-
"@type": "
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"animals": [{
|
|
13
|
+
"@type": "Animal",
|
|
14
|
+
"term.termType": "liveAnimal",
|
|
15
|
+
"value": "> 0"
|
|
15
16
|
}]
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -32,21 +33,32 @@ def _practice(value: float):
|
|
|
32
33
|
return practice
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
def _run(values: list):
|
|
37
|
+
# take a weighted average
|
|
38
|
+
value = weighted_average([
|
|
39
|
+
(p.get('lookup'), p.get('value')) for p in values
|
|
40
|
+
])
|
|
41
|
+
return [_practice(value)]
|
|
42
|
+
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
def _should_run(cycle: dict):
|
|
45
|
+
animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
|
|
46
|
+
values = [{
|
|
47
|
+
'id': p.get('term', {}).get('@id'),
|
|
48
|
+
'value': p.get('value'),
|
|
49
|
+
'lookup': get_lookup_value(p.get('term', {}), LOOKUPS['liveAnimal'])
|
|
50
|
+
} for p in animals]
|
|
51
|
+
has_animals = bool(animals)
|
|
52
|
+
has_values = all([all([p.get('value') is not None, p.get('lookup') is not None]) for p in values])
|
|
40
53
|
|
|
41
54
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
42
|
-
|
|
43
|
-
lookup_value=lookup_value)
|
|
55
|
+
values=log_as_table(values))
|
|
44
56
|
|
|
45
|
-
should_run = all([
|
|
57
|
+
should_run = all([has_animals, has_values])
|
|
46
58
|
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
47
|
-
return should_run,
|
|
59
|
+
return should_run, values
|
|
48
60
|
|
|
49
61
|
|
|
50
62
|
def run(cycle: dict):
|
|
51
|
-
should_run,
|
|
52
|
-
return
|
|
63
|
+
should_run, values = _should_run(cycle)
|
|
64
|
+
return _run(values) if should_run else []
|
|
@@ -5,7 +5,7 @@ from hestia_earth.models.utils.term import get_lookup_value
|
|
|
5
5
|
from . import MODEL
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def get_liveAnimal_term_id(product: dict, **log_ars):
|
|
9
9
|
term_id = get_lookup_value(product.get('term', {}), 'liveAnimalTermId', model=MODEL, **log_ars)
|
|
10
10
|
return term_id.split(';')[0] if term_id else None
|
|
11
11
|
|