hestia-earth-models 0.62.0__py3-none-any.whl → 0.62.2__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/utils.py +3 -2
- hestia_earth/models/cycle/coldCarcassWeightPerHead.py +4 -2
- hestia_earth/models/cycle/coldDressedCarcassWeightPerHead.py +2 -2
- hestia_earth/models/cycle/concentrateFeed.py +3 -3
- hestia_earth/models/cycle/feedConversionRatio/feedConversionRatioNitrogen.py +2 -1
- hestia_earth/models/cycle/post_checks/__init__.py +3 -2
- hestia_earth/models/cycle/post_checks/otherSites.py +40 -0
- hestia_earth/models/cycle/pre_checks/__init__.py +2 -1
- hestia_earth/models/cycle/pre_checks/otherSites.py +42 -0
- hestia_earth/models/cycle/pre_checks/site.py +1 -1
- hestia_earth/models/cycle/readyToCookWeightPerHead.py +2 -2
- hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
- hestia_earth/models/emepEea2019/utils.py +4 -3
- hestia_earth/models/geospatialDatabase/heavyWinterPrecipitation.py +1 -1
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +53 -43
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +30 -4
- hestia_earth/models/ipcc2019/n2OToAirExcretaDirect.py +6 -2
- hestia_earth/models/ipcc2019/n2OToAirExcretaIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +4 -2
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +210 -40
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +2 -6
- hestia_earth/models/ipcc2019/pastureGrass.py +44 -42
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +46 -92
- hestia_earth/models/mocking/search-results.json +378 -234
- hestia_earth/models/schererPfister2015/utils.py +2 -2
- hestia_earth/models/site/brackishWater.py +1 -1
- hestia_earth/models/site/flowingWater.py +1 -1
- hestia_earth/models/site/freshWater.py +1 -1
- hestia_earth/models/site/management.py +79 -38
- hestia_earth/models/site/pre_checks/cache_sources.py +9 -13
- hestia_earth/models/site/salineWater.py +1 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +12 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +12 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +11 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +11 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +12 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +12 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +12 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +12 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +11 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +11 -1
- hestia_earth/models/utils/blank_node.py +144 -110
- hestia_earth/models/utils/constant.py +2 -0
- hestia_earth/models/utils/lookup.py +19 -6
- hestia_earth/models/utils/property.py +6 -6
- hestia_earth/models/utils/site.py +7 -0
- hestia_earth/models/utils/source.py +1 -1
- hestia_earth/models/utils/term.py +21 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.2.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.2.dist-info}/RECORD +68 -63
- tests/models/cycle/post_checks/test_otherSites.py +15 -0
- tests/models/cycle/pre_checks/test_otherSites.py +21 -0
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +5 -3
- tests/models/ipcc2019/test_organicCarbonPerHa.py +10 -20
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_2_utils.py +0 -8
- tests/models/site/pre_checks/test_cache_sources.py +6 -10
- tests/models/site/test_management.py +192 -4
- tests/models/utils/test_blank_node.py +0 -281
- tests/models/utils/test_lookup.py +10 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.2.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.2.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.62.0.dist-info → hestia_earth_models-0.62.2.dist-info}/top_level.txt +0 -0
|
@@ -19,13 +19,14 @@ from hestia_earth.schema import (
|
|
|
19
19
|
)
|
|
20
20
|
from hestia_earth.utils.model import find_term_match, filter_list_term_type
|
|
21
21
|
from hestia_earth.utils.tools import flatten, list_sum, non_empty_list
|
|
22
|
+
from hestia_earth.utils.blank_node import get_node_value
|
|
22
23
|
|
|
23
24
|
from hestia_earth.models.utils.array_builders import (
|
|
24
25
|
avg_run_in_columnwise, gen_seed, grouped_avg, repeat_1d_array_as_columns
|
|
25
26
|
)
|
|
26
27
|
from hestia_earth.models.utils.blank_node import (
|
|
27
|
-
cumulative_nodes_lookup_match, cumulative_nodes_term_match,
|
|
28
|
-
group_nodes_by_year_and_month, GroupNodesByYearMode, node_term_match
|
|
28
|
+
cumulative_nodes_lookup_match, cumulative_nodes_term_match, group_nodes_by_year,
|
|
29
|
+
group_nodes_by_year_and_month, GroupNodesByYearMode, node_lookup_match, node_term_match
|
|
29
30
|
)
|
|
30
31
|
from hestia_earth.models.utils.cycle import check_cycle_site_ids_identical
|
|
31
32
|
from hestia_earth.models.utils.descriptive_stats import calc_descriptive_stats
|
|
@@ -35,16 +36,16 @@ from hestia_earth.models.utils.site import related_cycles
|
|
|
35
36
|
|
|
36
37
|
from .organicCarbonPerHa_utils import (
|
|
37
38
|
CarbonSource, check_consecutive, DEPTH_LOWER, DEPTH_UPPER, check_irrigation,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
sample_plus_minus_uncertainty, sample_truncated_normal, STATS_DEFINITION
|
|
39
|
+
get_cover_crop_property_terms_with_cache, get_upland_rice_crop_terms_with_cache,
|
|
40
|
+
get_upland_rice_land_cover_terms_with_cache, IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_LOOKUP_VALUE,
|
|
41
|
+
IPCC_MANAGEMENT_CATEGORY_TO_TILLAGE_MANAGEMENT_LOOKUP_VALUE, IpccLandUseCategory, IpccManagementCategory,
|
|
42
|
+
MIN_AREA_THRESHOLD, MIN_YIELD_THRESHOLD, sample_constant, sample_plus_minus_uncertainty, sample_truncated_normal,
|
|
43
|
+
STATS_DEFINITION
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
_LOOKUPS = {
|
|
47
47
|
"crop": "IPCC_LAND_USE_CATEGORY",
|
|
48
|
+
"landCover": "IPCC_LAND_USE_CATEGORY",
|
|
48
49
|
"tillage": "IPCC_TILLAGE_MANAGEMENT_CATEGORY"
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -58,10 +59,27 @@ _NUMBER_OF_TILLAGES_TERM_ID = "numberOfTillages"
|
|
|
58
59
|
_TEMPERATURE_MONTHLY_TERM_ID = "temperatureMonthly"
|
|
59
60
|
_PRECIPITATION_MONTHLY_TERM_ID = "precipitationMonthly"
|
|
60
61
|
_PET_MONTHLY_TERM_ID = "potentialEvapotranspirationMonthly"
|
|
62
|
+
_ABOVE_GROUND_CROP_RESIDUE_TOTAL_TERM_ID = "aboveGroundCropResidueTotal"
|
|
61
63
|
_CARBON_CONTENT_TERM_ID = "carbonContent"
|
|
62
64
|
_NITROGEN_CONTENT_TERM_ID = "nitrogenContent"
|
|
63
65
|
_LIGNIN_CONTENT_TERM_ID = "ligninContent"
|
|
64
66
|
|
|
67
|
+
_CROP_RESIDUE_MANAGEMENT_TERM_IDS = [
|
|
68
|
+
"residueIncorporated",
|
|
69
|
+
"residueIncorporatedLessThan30DaysBeforeCultivation",
|
|
70
|
+
"residueIncorporatedMoreThan30DaysBeforeCultivation",
|
|
71
|
+
"residueLeftOnField"
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
_CARBON_SOURCE_TERM_IDS = [
|
|
75
|
+
"discardedCropIncorporated",
|
|
76
|
+
"discardedCropLeftOnField",
|
|
77
|
+
"belowGroundCropResidue",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
_MIN_RESIDUE_LEFT_ON_FIELD = 20 # TODO: Confirm assumption
|
|
81
|
+
_DEFAULT_COVER_CROP_BIOMASS = 4000 # TODO: Confirm assumption, Source PAS 2050-1:2012
|
|
82
|
+
|
|
65
83
|
_CARBON_INPUT_PROPERTY_TERM_IDS = [
|
|
66
84
|
_CARBON_CONTENT_TERM_ID,
|
|
67
85
|
_NITROGEN_CONTENT_TERM_ID,
|
|
@@ -1283,8 +1301,8 @@ def _get_grouped_sand_content_measurements(grouped_measurements: dict) -> dict:
|
|
|
1283
1301
|
|
|
1284
1302
|
def _get_grouped_carbon_input_data(grouped_cycles: dict) -> dict:
|
|
1285
1303
|
grouped_carbon_sources = {
|
|
1286
|
-
year:
|
|
1287
|
-
for year,
|
|
1304
|
+
year: flatten([_get_carbon_sources(cycle) for cycle in cycles])
|
|
1305
|
+
for year, cycles in grouped_cycles.items()
|
|
1288
1306
|
}
|
|
1289
1307
|
|
|
1290
1308
|
return {
|
|
@@ -1296,67 +1314,219 @@ def _get_grouped_carbon_input_data(grouped_cycles: dict) -> dict:
|
|
|
1296
1314
|
}
|
|
1297
1315
|
|
|
1298
1316
|
|
|
1299
|
-
def
|
|
1317
|
+
def _get_carbon_sources(cycle: dict) -> list[CarbonSource]:
|
|
1300
1318
|
"""
|
|
1301
|
-
|
|
1319
|
+
Extract and format the carbon source data from a cycle's inputs and products.
|
|
1302
1320
|
|
|
1303
1321
|
Carbon sources can be either a Hestia `Product` node (e.g. crop residue) or `Input` node (e.g. organic amendment).
|
|
1304
1322
|
|
|
1305
1323
|
Parameters
|
|
1306
1324
|
----------
|
|
1307
|
-
|
|
1308
|
-
A
|
|
1325
|
+
cycle : list[dict]
|
|
1326
|
+
A Hestia `Cycle` node, see: https://www.hestia.earth/schema/Cycle.
|
|
1309
1327
|
|
|
1310
1328
|
Returns
|
|
1311
1329
|
-------
|
|
1312
1330
|
list[CarbonSource]
|
|
1313
|
-
A formatted list of `CarbonSource`s
|
|
1331
|
+
A formatted list of `CarbonSource`s.
|
|
1314
1332
|
"""
|
|
1315
|
-
inputs_and_products =
|
|
1316
|
-
[cycle.get("inputs", []) + cycle.get("products", []) for cycle in cycles]
|
|
1317
|
-
))
|
|
1318
|
-
|
|
1333
|
+
inputs_and_products = cycle.get("inputs", []) + cycle.get("products", [])
|
|
1319
1334
|
return non_empty_list([
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1335
|
+
next(
|
|
1336
|
+
(_func(node, cycle) for validator, _func in _CARBON_SOURCE_DECISION_TREE.items() if validator(node)),
|
|
1337
|
+
None
|
|
1338
|
+
) for node in inputs_and_products
|
|
1339
|
+
])
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
def _should_run_carbon_source_ag_residue(node: dict) -> bool:
|
|
1343
|
+
"""
|
|
1344
|
+
Determine whether an input or product is a valid above-ground biomass carbon source.
|
|
1345
|
+
|
|
1346
|
+
Parameters
|
|
1347
|
+
----------
|
|
1348
|
+
node : dict
|
|
1349
|
+
A Hestia [Input](https://www.hestia.earth/schema/Input) or [Product](https://www.hestia.earth/schema/Product)
|
|
1350
|
+
node.
|
|
1351
|
+
|
|
1352
|
+
Returns
|
|
1353
|
+
-------
|
|
1354
|
+
bool
|
|
1355
|
+
Whether the node satisfies the critera.
|
|
1356
|
+
"""
|
|
1357
|
+
return node.get("term", {}).get("@id") == _ABOVE_GROUND_CROP_RESIDUE_TOTAL_TERM_ID
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
def _calc_carbon_source_ag_crop_residue(node: dict, cycle: dict) -> Union[CarbonSource, None]:
|
|
1361
|
+
"""
|
|
1362
|
+
Extract and format the carbon source data for above-ground crop residues.
|
|
1363
|
+
|
|
1364
|
+
n.b., We assume that even if a cycle's residue management states that 100% of above-ground crop residues are
|
|
1365
|
+
removed or burnt, a minimal amount of crop residues do remain on site to become a carbon source (see
|
|
1366
|
+
`_MIN_RESIDUE_LEFT_ON_FIELD` variable).
|
|
1367
|
+
|
|
1368
|
+
Parameters
|
|
1369
|
+
----------
|
|
1370
|
+
node : dict
|
|
1371
|
+
A Hestia [Product](https://www.hestia.earth/schema/Product) node with `term.termType` == `landCover`.
|
|
1372
|
+
|
|
1373
|
+
Returns
|
|
1374
|
+
-------
|
|
1375
|
+
CarbonSource | None
|
|
1376
|
+
The carbon source data of the above-ground residues, or `None` if carbon source data incomplete.
|
|
1377
|
+
"""
|
|
1378
|
+
value = get_node_value(node)
|
|
1379
|
+
residue_left_on_field = list_sum([
|
|
1380
|
+
get_node_value(practice) for practice in cycle.get("practices", [])
|
|
1381
|
+
if node_term_match(practice, _CROP_RESIDUE_MANAGEMENT_TERM_IDS)
|
|
1382
|
+
])
|
|
1383
|
+
mass = value * max(residue_left_on_field, _MIN_RESIDUE_LEFT_ON_FIELD) / 100
|
|
1384
|
+
|
|
1385
|
+
carbon_source = CarbonSource(
|
|
1386
|
+
mass,
|
|
1387
|
+
*_retrieve_carbon_source_properties(node)
|
|
1388
|
+
)
|
|
1389
|
+
|
|
1390
|
+
return carbon_source if _validate_carbon_source(carbon_source) else None
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
def _should_run_carbon_source_cover_crop(node: dict) -> bool:
|
|
1394
|
+
"""
|
|
1395
|
+
Determine whether a product is a valid above cover crop carbon source.
|
|
1396
|
+
|
|
1397
|
+
Parameters
|
|
1398
|
+
----------
|
|
1399
|
+
node : dict
|
|
1400
|
+
A Hestia [Input](https://www.hestia.earth/schema/Input) or [Product](https://www.hestia.earth/schema/Product)
|
|
1401
|
+
node.
|
|
1402
|
+
|
|
1403
|
+
Returns
|
|
1404
|
+
-------
|
|
1405
|
+
bool
|
|
1406
|
+
Whether the node satisfies the critera.
|
|
1407
|
+
"""
|
|
1408
|
+
LOOKUP = _LOOKUPS["landCover"]
|
|
1409
|
+
return all([
|
|
1410
|
+
node.get("term", {}).get("termType") in [TermTermType.LANDCOVER.value],
|
|
1411
|
+
node_lookup_match(
|
|
1412
|
+
node, LOOKUP, IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_LOOKUP_VALUE[IpccLandUseCategory.ANNUAL_CROPS]
|
|
1413
|
+
),
|
|
1414
|
+
any(
|
|
1415
|
+
get_node_property(node, term_id, False).get("value", False)
|
|
1416
|
+
for term_id in get_cover_crop_property_terms_with_cache()
|
|
1417
|
+
)
|
|
1325
1418
|
])
|
|
1326
1419
|
|
|
1327
1420
|
|
|
1328
|
-
def
|
|
1421
|
+
def _calc_carbon_source_cover_crop(node: dict, *_) -> Union[CarbonSource, None]:
|
|
1329
1422
|
"""
|
|
1330
|
-
|
|
1423
|
+
Extract and format the carbon source data for an annual cover crop.
|
|
1424
|
+
|
|
1425
|
+
n.b., We make the assumption that the entirety of the cover crop's biomass remains on site.
|
|
1331
1426
|
|
|
1332
1427
|
Parameters
|
|
1333
1428
|
----------
|
|
1334
1429
|
node : dict
|
|
1335
|
-
A Hestia
|
|
1336
|
-
or https://www.hestia.earth/schema/Input.
|
|
1430
|
+
A Hestia [Product](https://www.hestia.earth/schema/Product) node with `term.termType` == `landCover`.
|
|
1337
1431
|
|
|
1338
1432
|
Returns
|
|
1339
1433
|
-------
|
|
1340
1434
|
CarbonSource | None
|
|
1341
|
-
|
|
1435
|
+
The carbon source data of the cover crop, or `None` if carbon source data incomplete.
|
|
1436
|
+
"""
|
|
1437
|
+
value = get_node_value(node)
|
|
1438
|
+
carbon_source = CarbonSource(
|
|
1439
|
+
_DEFAULT_COVER_CROP_BIOMASS * value / 100,
|
|
1440
|
+
_Parameter.DEFAULT_CARBON_CONTENT.value.get("value"),
|
|
1441
|
+
_Parameter.DEFAULT_NITROGEN_CONTENT.value.get("value"),
|
|
1442
|
+
_Parameter.DEFAULT_NITROGEN_CONTENT.value.get("value")
|
|
1443
|
+
)
|
|
1444
|
+
return carbon_source
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
def _should_run_carbon_source(node: dict) -> bool:
|
|
1448
|
+
"""
|
|
1449
|
+
Determine whether an input or product is a valid carbon source.
|
|
1450
|
+
|
|
1451
|
+
Parameters
|
|
1452
|
+
----------
|
|
1453
|
+
node : dict
|
|
1454
|
+
A Hestia [Input](https://www.hestia.earth/schema/Input) or [Product](https://www.hestia.earth/schema/Product)
|
|
1455
|
+
node.
|
|
1456
|
+
|
|
1457
|
+
Returns
|
|
1458
|
+
-------
|
|
1459
|
+
bool
|
|
1460
|
+
Whether the node satisfies the critera.
|
|
1461
|
+
"""
|
|
1462
|
+
return any([
|
|
1463
|
+
node.get("term", {}).get("@id") in _CARBON_SOURCE_TERM_IDS,
|
|
1464
|
+
node.get("term", {}).get("termType") in _CARBON_SOURCE_TERM_TYPES
|
|
1465
|
+
])
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
def _calc_carbon_source(node: dict, *_) -> Union[CarbonSource, None]:
|
|
1469
|
+
"""
|
|
1470
|
+
Extract and format the carbon source data for an input or product.
|
|
1471
|
+
|
|
1472
|
+
Parameters
|
|
1473
|
+
----------
|
|
1474
|
+
node : dict
|
|
1475
|
+
A Hestia [Input](https://www.hestia.earth/schema/Input) or [Product](https://www.hestia.earth/schema/Product)
|
|
1476
|
+
node.
|
|
1477
|
+
|
|
1478
|
+
Returns
|
|
1479
|
+
-------
|
|
1480
|
+
CarbonSource | None
|
|
1481
|
+
The carbon source data of the cover crop, or `None` if carbon source data incomplete.
|
|
1482
|
+
"""
|
|
1483
|
+
carbon_source = CarbonSource(
|
|
1484
|
+
get_node_value(node),
|
|
1485
|
+
*_retrieve_carbon_source_properties(node)
|
|
1486
|
+
)
|
|
1487
|
+
|
|
1488
|
+
return carbon_source if _validate_carbon_source(carbon_source) else None
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
def _retrieve_carbon_source_properties(node: dict) -> tuple[float, float, float]:
|
|
1492
|
+
"""
|
|
1493
|
+
Extract the carbon source properties from an input or product node or, if required, retrieve them from default
|
|
1494
|
+
properties.
|
|
1495
|
+
|
|
1496
|
+
Parameters
|
|
1497
|
+
----------
|
|
1498
|
+
node : dict
|
|
1499
|
+
A Hestia [Input](https://www.hestia.earth/schema/Input) or [Product](https://www.hestia.earth/schema/Product)
|
|
1500
|
+
node.
|
|
1501
|
+
|
|
1502
|
+
Returns
|
|
1503
|
+
-------
|
|
1504
|
+
tuple[float, float, float]
|
|
1505
|
+
`(carbon_content, nitrogen_content, lignin_content)`
|
|
1342
1506
|
"""
|
|
1343
|
-
mass = list_sum(node.get("value", []))
|
|
1344
1507
|
carbon_content, nitrogen_content, lignin_content = (
|
|
1345
1508
|
get_node_property(node, term_id).get("value", 0)/100 for term_id in _CARBON_INPUT_PROPERTY_TERM_IDS
|
|
1346
1509
|
)
|
|
1510
|
+
return carbon_content, nitrogen_content, lignin_content
|
|
1347
1511
|
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1512
|
+
|
|
1513
|
+
def _validate_carbon_source(carbon_source: CarbonSource) -> bool:
|
|
1514
|
+
"""
|
|
1515
|
+
Validate that a `CarbonSource` named tuple is data complete.
|
|
1516
|
+
"""
|
|
1517
|
+
return all([
|
|
1518
|
+
carbon_source.mass > 0,
|
|
1519
|
+
0 < carbon_source.carbon_content <= 1,
|
|
1520
|
+
0 < carbon_source.nitrogen_content <= 1,
|
|
1521
|
+
0 < carbon_source.lignin_content <= 1
|
|
1353
1522
|
])
|
|
1354
1523
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1524
|
+
|
|
1525
|
+
_CARBON_SOURCE_DECISION_TREE = {
|
|
1526
|
+
_should_run_carbon_source_ag_residue: _calc_carbon_source_ag_crop_residue,
|
|
1527
|
+
_should_run_carbon_source_cover_crop: _calc_carbon_source_cover_crop,
|
|
1528
|
+
_should_run_carbon_source: _calc_carbon_source,
|
|
1529
|
+
}
|
|
1360
1530
|
|
|
1361
1531
|
|
|
1362
1532
|
def _calc_total_organic_carbon_input(
|
|
@@ -10,8 +10,8 @@ from hestia_earth.models.utils.array_builders import (
|
|
|
10
10
|
)
|
|
11
11
|
from hestia_earth.models.utils.blank_node import cumulative_nodes_term_match
|
|
12
12
|
from hestia_earth.models.utils.term import (
|
|
13
|
-
get_cover_crop_property_terms,
|
|
14
|
-
|
|
13
|
+
get_cover_crop_property_terms, get_irrigated_terms, get_residue_removed_or_burnt_terms, get_upland_rice_crop_terms,
|
|
14
|
+
get_upland_rice_land_cover_terms
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
STATS_DEFINITION = MeasurementStatsDefinition.SIMULATED.value
|
|
@@ -27,10 +27,6 @@ def get_cover_crop_property_terms_with_cache():
|
|
|
27
27
|
return lru_cache()(get_cover_crop_property_terms)()
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def get_crop_residue_inc_or_left_terms_with_cache():
|
|
31
|
-
return lru_cache()(get_crop_residue_incorporated_or_left_on_field_terms)()
|
|
32
|
-
|
|
33
|
-
|
|
34
30
|
def get_irrigated_terms_with_cache():
|
|
35
31
|
return lru_cache()(get_irrigated_terms)()
|
|
36
32
|
|
|
@@ -12,7 +12,8 @@ from hestia_earth.schema import TermTermType
|
|
|
12
12
|
from hestia_earth.utils.model import filter_list_term_type
|
|
13
13
|
from hestia_earth.utils.tools import list_sum
|
|
14
14
|
|
|
15
|
-
from hestia_earth.models.log import logRequirements, logShouldRun,
|
|
15
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
16
|
+
from hestia_earth.models.utils.blank_node import lookups_logs, properties_logs
|
|
16
17
|
from hestia_earth.models.utils.input import _new_input
|
|
17
18
|
from hestia_earth.models.utils.term import get_wool_terms
|
|
18
19
|
from hestia_earth.models.utils.completeness import _is_term_type_complete, _is_term_type_incomplete
|
|
@@ -25,6 +26,7 @@ from .pastureGrass_utils import (
|
|
|
25
26
|
calculate_REM,
|
|
26
27
|
calculate_REG,
|
|
27
28
|
calculate_NEfeed,
|
|
29
|
+
calculate_GE,
|
|
28
30
|
product_wool_energy,
|
|
29
31
|
get_animals,
|
|
30
32
|
get_animal_values
|
|
@@ -119,7 +121,8 @@ REQUIREMENTS = {
|
|
|
119
121
|
}
|
|
120
122
|
LOOKUPS = {
|
|
121
123
|
"animalManagement": [
|
|
122
|
-
"mjKgEvMilkIpcc2019"
|
|
124
|
+
"mjKgEvMilkIpcc2019",
|
|
125
|
+
"defaultFatContentEvMilkIpcc2019"
|
|
123
126
|
],
|
|
124
127
|
"animalProduct": ["mjKgEvWoolNetEnergyWoolIpcc2019"],
|
|
125
128
|
"liveAnimal": [
|
|
@@ -127,7 +130,8 @@ LOOKUPS = {
|
|
|
127
130
|
"mjDayKgCfiNetEnergyMaintenanceIpcc2019",
|
|
128
131
|
"ratioCPregnancyNetEnergyPregnancyIpcc2019",
|
|
129
132
|
"ratioCNetEnergyGrowthCattleBuffaloIpcc2019",
|
|
130
|
-
"mjKgABNetEnergyGrowthSheepGoatsIpcc2019"
|
|
133
|
+
"mjKgABNetEnergyGrowthSheepGoatsIpcc2019",
|
|
134
|
+
"isWoolProducingAnimal"
|
|
131
135
|
],
|
|
132
136
|
"system-liveAnimal-activityCoefficient-ipcc2019": "using animal term @id",
|
|
133
137
|
"crop-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"],
|
|
@@ -150,9 +154,6 @@ def _input(term_id: str, value: float):
|
|
|
150
154
|
return node
|
|
151
155
|
|
|
152
156
|
|
|
153
|
-
def _sum_values(values: list, index=0): return list_sum([v[index] for v in values])
|
|
154
|
-
|
|
155
|
-
|
|
156
157
|
def calculate_NEwool(cycle: dict) -> float:
|
|
157
158
|
term_ids = get_wool_terms()
|
|
158
159
|
products = [p for p in cycle.get('products', []) if p.get('term', {}).get('@id') in term_ids]
|
|
@@ -162,39 +163,20 @@ def calculate_NEwool(cycle: dict) -> float:
|
|
|
162
163
|
return sum([value * lookup_value for (value, lookup_value) in product_values])
|
|
163
164
|
|
|
164
165
|
|
|
165
|
-
def _calculate_GE(
|
|
166
|
-
cycle: dict, animals: list, REM: float, REG: float, NEwool: float, NEm_feed: float, NEg_feed: float, system: dict
|
|
167
|
-
) -> float:
|
|
168
|
-
values = [get_animal_values(cycle, animal, system) for animal in animals]
|
|
169
|
-
NEm = _sum_values(values, 0)
|
|
170
|
-
NEa = _sum_values(values, 1)
|
|
171
|
-
NEl = _sum_values(values, 2)
|
|
172
|
-
NEwork = _sum_values(values, 3)
|
|
173
|
-
NEp = _sum_values(values, 4)
|
|
174
|
-
NEg = _sum_values(values, 5)
|
|
175
|
-
|
|
176
|
-
debugValues(cycle, model=MODEL, term=MODEL_KEY, model_key=MODEL_KEY,
|
|
177
|
-
NEm=NEm,
|
|
178
|
-
NEa=NEa,
|
|
179
|
-
NEl=NEl,
|
|
180
|
-
NEwork=NEwork,
|
|
181
|
-
NEp=NEp,
|
|
182
|
-
NEg=NEg,
|
|
183
|
-
NEm_feed=NEm_feed,
|
|
184
|
-
NEg_feed=NEg_feed)
|
|
185
|
-
|
|
186
|
-
return (NEm + NEa + NEl + NEwork + NEp - NEm_feed)/REM + (NEg + NEwool - NEg_feed)/REG
|
|
187
|
-
|
|
188
|
-
|
|
189
166
|
def _run_practice(cycle: dict, meanDE: float, meanECHHV: float, system: dict):
|
|
190
167
|
animals = get_animals(cycle)
|
|
191
168
|
REM = calculate_REM(meanDE)
|
|
192
169
|
REG = calculate_REG(meanDE)
|
|
193
170
|
NEwool = calculate_NEwool(cycle)
|
|
194
171
|
NEm_feed, NEg_feed = calculate_NEfeed(cycle)
|
|
172
|
+
|
|
173
|
+
animal_values = [{
|
|
174
|
+
'animalId': animal.get('term', {}).get('@id')
|
|
175
|
+
} | get_animal_values(cycle, animal, system) for animal in animals]
|
|
176
|
+
|
|
195
177
|
GE = (
|
|
196
|
-
|
|
197
|
-
) if
|
|
178
|
+
calculate_GE(animal_values, REM, REG, NEwool, NEm_feed, NEg_feed) / (meanDE/100)
|
|
179
|
+
) if meanDE else 0
|
|
198
180
|
|
|
199
181
|
def run(practice: dict):
|
|
200
182
|
key = practice.get('key', {})
|
|
@@ -202,14 +184,34 @@ def _run_practice(cycle: dict, meanDE: float, meanECHHV: float, system: dict):
|
|
|
202
184
|
input_term_id = practice_input_id(practice)
|
|
203
185
|
value = (GE / meanECHHV) * (list_sum(practice.get('value', [0])) / 100)
|
|
204
186
|
|
|
187
|
+
logs = log_as_table([v | {
|
|
188
|
+
'practiceKeyId': key_id,
|
|
189
|
+
'REM': REM,
|
|
190
|
+
'REG': REG,
|
|
191
|
+
'NEwool': NEwool,
|
|
192
|
+
'NEmFeed': NEm_feed,
|
|
193
|
+
'NEgFeed': NEg_feed,
|
|
194
|
+
'GE': GE,
|
|
195
|
+
'meanECHHV': meanECHHV,
|
|
196
|
+
'meanDE': meanDE
|
|
197
|
+
} for v in animal_values])
|
|
198
|
+
animal_lookups = lookups_logs(MODEL, animals, LOOKUPS, model_key=MODEL_KEY, term=input_term_id)
|
|
199
|
+
animal_properties = properties_logs(animals, properties=[
|
|
200
|
+
'liveweightPerHead',
|
|
201
|
+
'hoursWorkedPerDay',
|
|
202
|
+
'animalsPerBirth',
|
|
203
|
+
'pregnancyRateTotal',
|
|
204
|
+
'weightAtMaturity',
|
|
205
|
+
'liveweightGain',
|
|
206
|
+
'weightAtWeaning',
|
|
207
|
+
'weightAtOneYear',
|
|
208
|
+
'weightAtSlaughter'
|
|
209
|
+
])
|
|
210
|
+
|
|
205
211
|
logRequirements(cycle, model=MODEL, term=input_term_id, model_key=MODEL_KEY,
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
NEm_feed=NEm_feed,
|
|
210
|
-
NEg_feed=NEg_feed,
|
|
211
|
-
GE=GE,
|
|
212
|
-
key_id=key_id)
|
|
212
|
+
animal_logs=logs,
|
|
213
|
+
animal_lookups=animal_lookups,
|
|
214
|
+
animal_properties=animal_properties)
|
|
213
215
|
|
|
214
216
|
logShouldRun(cycle, MODEL, input_term_id, True, model_key=MODEL_KEY)
|
|
215
217
|
|
|
@@ -242,15 +244,15 @@ def _should_run(cycle: dict, practices: dict):
|
|
|
242
244
|
meanECHHV > 0
|
|
243
245
|
])
|
|
244
246
|
|
|
245
|
-
for term_id in [
|
|
247
|
+
for term_id in [practice_input_id(p) for p in practices] or [MODEL_KEY]:
|
|
246
248
|
logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
247
249
|
term_type_animalFeed_complete=animalFeed_complete,
|
|
248
250
|
term_type_animalPopulation_complete=animalPopulation_complete,
|
|
249
251
|
term_type_freshForage_incomplete=freshForage_incomplete,
|
|
250
252
|
has_cycle_inputs_feed=has_cycle_inputs_feed,
|
|
251
253
|
all_animals_have_value=all_animals_have_value,
|
|
252
|
-
meanDE=
|
|
253
|
-
meanECHHV=
|
|
254
|
+
meanDE=calculate_meanDE(practices, term=term_id),
|
|
255
|
+
meanECHHV=calculate_meanECHHV(practices, term=term_id))
|
|
254
256
|
|
|
255
257
|
logShouldRun(cycle, MODEL, term_id, should_run, model_key=MODEL_KEY)
|
|
256
258
|
|