hestia-earth-models 0.72.2__py3-none-any.whl → 0.73.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hestia_earth/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +1 -1
- hestia_earth/models/akagiEtAl2011/ch4ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/nh3ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/noxToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/pm25ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/so2ToAirCropResidueBurning.py +32 -0
- hestia_earth/models/akagiEtAl2011/utils.py +45 -0
- hestia_earth/models/aware/scarcityWeightedWaterUse.py +2 -2
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/utils.py +1 -1
- hestia_earth/models/config/Cycle.json +48 -7
- hestia_earth/models/config/ImpactAssessment.json +22 -0
- hestia_earth/models/cycle/completeness/soilAmendment.py +1 -1
- hestia_earth/models/cycle/product/economicValueShare.py +3 -1
- hestia_earth/models/cycle/product/price.py +35 -10
- hestia_earth/models/cycle/product/revenue.py +5 -2
- hestia_earth/models/dammgen2009/noxToAirExcreta.py +14 -18
- hestia_earth/models/ecoinventV3/__init__.py +11 -6
- hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
- hestia_earth/models/emepEea2019/utils.py +2 -1
- hestia_earth/models/faostat2018/liveweightPerHead.py +1 -1
- hestia_earth/models/faostat2018/product/price.py +2 -2
- hestia_earth/models/faostat2018/seed.py +3 -2
- hestia_earth/models/faostat2018/utils.py +6 -5
- hestia_earth/models/geospatialDatabase/altitude.py +2 -1
- hestia_earth/models/geospatialDatabase/drainageClass.py +2 -1
- hestia_earth/models/geospatialDatabase/organicCarbonPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/totalNitrogenPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/totalPhosphorusPerKgSoil.py +2 -1
- hestia_earth/models/geospatialDatabase/utils.py +1 -1
- hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +1 -1
- hestia_earth/models/hestia/brackishWater.py +1 -1
- hestia_earth/models/hestia/default_emissions.py +105 -0
- hestia_earth/models/hestia/default_resourceUse.py +110 -0
- hestia_earth/models/hestia/freshWater.py +1 -1
- hestia_earth/models/hestia/inorganicFertiliser.py +12 -12
- hestia_earth/models/hestia/landCover.py +7 -5
- hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +3 -0
- hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +3 -0
- hestia_earth/models/hestia/liveAnimal.py +1 -1
- hestia_earth/models/hestia/management.py +1 -1
- hestia_earth/models/hestia/netPrimaryProduction.py +1 -1
- hestia_earth/models/hestia/organicCarbonPerHa.py +2 -2
- hestia_earth/models/hestia/salineWater.py +1 -1
- hestia_earth/models/hestia/seed_emissions.py +34 -20
- hestia_earth/models/hestia/totalNitrogenPerKgSoil.py +1 -1
- hestia_earth/models/hestia/waterSalinity.py +2 -1
- hestia_earth/models/ipcc2006/aboveGroundCropResidueRemoved.py +2 -2
- hestia_earth/models/ipcc2006/aboveGroundCropResidueTotal.py +10 -6
- hestia_earth/models/ipcc2006/belowGroundCropResidue.py +12 -8
- hestia_earth/models/ipcc2019/animal/utils.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
- hestia_earth/models/ipcc2019/carbonContent.py +1 -1
- hestia_earth/models/ipcc2019/ch4ToAirAquacultureSystems.py +17 -9
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +6 -6
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +4 -2
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +1 -1
- hestia_earth/models/ipcc2019/croppingDuration.py +4 -2
- hestia_earth/models/ipcc2019/ligninContent.py +1 -1
- hestia_earth/models/{akagiEtAl2011AndIpcc2006 → ipcc2019}/n2OToAirCropResidueBurningDirect.py +8 -4
- hestia_earth/models/ipcc2019/nitrogenContent.py +1 -1
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +6 -2
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +13 -12
- hestia_earth/models/ipcc2019/utils.py +6 -2
- hestia_earth/models/koble2014/residueBurnt.py +6 -3
- hestia_earth/models/koble2014/residueRemoved.py +1 -1
- hestia_earth/models/mocking/search-results.json +1577 -1573
- hestia_earth/models/pooreNemecek2018/aboveGroundCropResidueTotal.py +1 -1
- hestia_earth/models/pooreNemecek2018/belowGroundCropResidue.py +1 -1
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +1 -1
- hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +1 -1
- hestia_earth/models/pooreNemecek2018/longFallowDuration.py +1 -1
- hestia_earth/models/pooreNemecek2018/nurseryDensity.py +1 -1
- hestia_earth/models/pooreNemecek2018/nurseryDuration.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationDensity.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationLifespan.py +1 -1
- hestia_earth/models/pooreNemecek2018/plantationProductiveLifespan.py +3 -1
- hestia_earth/models/pooreNemecek2018/saplingsDepreciatedAmountPerCycle.py +1 -1
- hestia_earth/models/resourceUseNotRelevant/__init__.py +65 -0
- hestia_earth/models/schererPfister2015/nErosionSoilFlux.py +5 -3
- hestia_earth/models/schererPfister2015/pErosionSoilFlux.py +5 -3
- hestia_earth/models/schererPfister2015/utils.py +5 -4
- hestia_earth/models/stehfestBouwman2006/n2OToAirSoilFlux_utils.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirSoilFlux_utils.py +3 -3
- hestia_earth/models/utils/background_emissions.py +14 -10
- hestia_earth/models/utils/blank_node.py +6 -4
- hestia_earth/models/utils/crop.py +1 -1
- hestia_earth/models/utils/cropResidue.py +16 -0
- hestia_earth/models/utils/cycle.py +1 -1
- hestia_earth/models/utils/ecoClimateZone.py +2 -2
- hestia_earth/models/utils/excretaManagement.py +1 -1
- hestia_earth/models/utils/feedipedia.py +3 -3
- hestia_earth/models/utils/fertiliser.py +7 -1
- hestia_earth/models/utils/inorganicFertiliser.py +2 -2
- hestia_earth/models/utils/input.py +34 -1
- hestia_earth/models/utils/liveAnimal.py +2 -2
- hestia_earth/models/utils/lookup.py +1 -1
- hestia_earth/models/utils/measurement.py +5 -4
- hestia_earth/models/utils/productivity.py +1 -1
- hestia_earth/models/utils/property.py +4 -2
- hestia_earth/models/utils/site.py +2 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/RECORD +124 -113
- tests/models/akagiEtAl2011/test_ch4ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_nh3ToAirCropResidueBurning.py +33 -0
- tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/test_noxToAirCropResidueBurning.py +5 -17
- tests/models/akagiEtAl2011/test_pm25ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_so2ToAirCropResidueBurning.py +33 -0
- tests/models/akagiEtAl2011/test_utils.py +18 -0
- tests/models/cycle/product/test_price.py +1 -11
- tests/models/dammgen2009/test_noxToAirExcreta.py +30 -10
- tests/models/geospatialDatabase/test_utils.py +2 -1
- tests/models/hestia/test_default_emissions.py +25 -0
- tests/models/hestia/test_default_resourceUse.py +26 -0
- tests/models/hestia/test_landCover.py +2 -2
- tests/models/ipcc2019/test_ch4ToAirAquacultureSystems.py +2 -2
- tests/models/{akagiEtAl2011AndIpcc2006/test_nh3ToAirCropResidueBurning.py → ipcc2019/test_n2OToAirCropResidueBurningDirect.py} +2 -2
- tests/models/test_resourceUseNotRelevant.py +27 -0
- tests/models/{akagiEtAl2011AndIpcc2006/test_utils.py → utils/test_cropResidue.py} +6 -6
- hestia_earth/models/akagiEtAl2011AndIpcc2006/ch4ToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/nh3ToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/noxToAirCropResidueBurning.py +0 -57
- hestia_earth/models/akagiEtAl2011AndIpcc2006/utils.py +0 -15
- tests/models/akagiEtAl2011AndIpcc2006/test_ch4ToAirCropResidueBurning.py +0 -45
- tests/models/akagiEtAl2011AndIpcc2006/test_n2OToAirCropResidueBurningDirect.py +0 -46
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/top_level.txt +0 -0
- /tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +0 -0
@@ -31,7 +31,7 @@ def _product(value: float):
|
|
31
31
|
|
32
32
|
def _get_lookup_value(product: dict):
|
33
33
|
term_id = product.get('term', {}).get('@id', '')
|
34
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
34
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
35
35
|
|
36
36
|
|
37
37
|
def _run(product: dict):
|
@@ -31,7 +31,7 @@ def _product(value: float):
|
|
31
31
|
|
32
32
|
def _get_lookup_value(product: dict):
|
33
33
|
term_id = product.get('term', {}).get('@id', '')
|
34
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
34
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
35
35
|
|
36
36
|
|
37
37
|
def _run(product: dict):
|
@@ -131,7 +131,7 @@ def _run(excreta_vs_products: list, excreta_n_products: list, mass_balance_items
|
|
131
131
|
def _get_carbonContent(cycle: dict):
|
132
132
|
primary_prod = find_primary_product(cycle) or {}
|
133
133
|
return safe_parse_float(
|
134
|
-
get_lookup_value(primary_prod.get('term', {}), 'carbonContent', model=MODEL, model_key=MODEL_KEY)
|
134
|
+
get_lookup_value(primary_prod.get('term', {}), 'carbonContent', model=MODEL, model_key=MODEL_KEY), default=0
|
135
135
|
) / 100
|
136
136
|
|
137
137
|
|
@@ -58,7 +58,7 @@ def _get_conveyancing_efficiency(impact_assessment: dict, product: dict):
|
|
58
58
|
debugValues(impact_assessment, model=MODEL, term=TERM_ID,
|
59
59
|
grouping=grouping,
|
60
60
|
conveyancing_efficiency=value)
|
61
|
-
return safe_parse_float(value, 1)
|
61
|
+
return safe_parse_float(value, default=1)
|
62
62
|
|
63
63
|
|
64
64
|
def _run(impact_assessment: dict, product: dict, irrigation: float):
|
@@ -29,7 +29,7 @@ def _practice(value: float):
|
|
29
29
|
|
30
30
|
def _get_value(product: dict):
|
31
31
|
term_id = product.get('term', {}).get('@id', '')
|
32
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
32
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
33
33
|
|
34
34
|
|
35
35
|
def _run(product: dict):
|
@@ -23,7 +23,7 @@ TERM_ID = 'nurseryDensity'
|
|
23
23
|
|
24
24
|
def _get_value(product: dict):
|
25
25
|
term_id = product.get('term', {}).get('@id', '')
|
26
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
26
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
27
27
|
|
28
28
|
|
29
29
|
def _practice(value: float):
|
@@ -29,7 +29,7 @@ def _practice(value: float):
|
|
29
29
|
|
30
30
|
def _get_value(product: dict):
|
31
31
|
term_id = product.get('term', {}).get('@id', '')
|
32
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
32
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
33
33
|
|
34
34
|
|
35
35
|
def run(cycle: dict):
|
@@ -29,7 +29,7 @@ def _practice(value: float):
|
|
29
29
|
|
30
30
|
def _get_value(product: dict):
|
31
31
|
term_id = product.get('term', {}).get('@id', '')
|
32
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
32
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
33
33
|
|
34
34
|
|
35
35
|
def run(cycle: dict):
|
@@ -23,7 +23,7 @@ TERM_ID = 'plantationLifespan'
|
|
23
23
|
|
24
24
|
def _get_value(product: dict):
|
25
25
|
term_id = product.get('term', {}).get('@id', '')
|
26
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
26
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
27
27
|
|
28
28
|
|
29
29
|
def _practice(value: float):
|
@@ -33,7 +33,9 @@ def _get_value(cycle: dict):
|
|
33
33
|
def get(product: dict):
|
34
34
|
term_id = product.get('term', {}).get('@id', '')
|
35
35
|
plantationLifespan = get_plantationLifespan(product)
|
36
|
-
nonProductiveLifespan = safe_parse_float(
|
36
|
+
nonProductiveLifespan = safe_parse_float(
|
37
|
+
get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None
|
38
|
+
)
|
37
39
|
product_id = product.get('term').get('@id')
|
38
40
|
product_id_logs = log_as_table({
|
39
41
|
'plantationLifespan': plantationLifespan,
|
@@ -35,7 +35,7 @@ def _input(value: float):
|
|
35
35
|
|
36
36
|
def _get_value(product: dict):
|
37
37
|
term_id = product.get('term', {}).get('@id', '')
|
38
|
-
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
|
38
|
+
return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
|
39
39
|
|
40
40
|
|
41
41
|
def _run(product: dict, plantationLifespan: float, cycleDuration: float):
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from hestia_earth.schema import IndicatorMethodTier, TermTermType
|
2
|
+
from hestia_earth.utils.lookup import download_lookup, lookup_term_ids
|
3
|
+
from hestia_earth.utils.lookup_utils import is_in_system_boundary
|
4
|
+
|
5
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
6
|
+
from hestia_earth.models.utils.indicator import _new_indicator
|
7
|
+
from hestia_earth.models.utils.blank_node import _run_required
|
8
|
+
from hestia_earth.models.utils.impact_assessment import get_site
|
9
|
+
from hestia_earth.models.utils.site import get_land_cover_term_id
|
10
|
+
|
11
|
+
REQUIREMENTS = {
|
12
|
+
"ImpactAssessment": {
|
13
|
+
"emissionsResourceUse": [{"@type": "Indicator"}]
|
14
|
+
}
|
15
|
+
}
|
16
|
+
RETURNS = {
|
17
|
+
"Indicator": [{
|
18
|
+
"value": "0",
|
19
|
+
"methodTier": "not relevant"
|
20
|
+
}]
|
21
|
+
}
|
22
|
+
LOOKUPS = {
|
23
|
+
"resourceUse": [
|
24
|
+
"term.id",
|
25
|
+
"inHestiaDefaultSystemBoundary",
|
26
|
+
"siteTypesAllowed"
|
27
|
+
]
|
28
|
+
}
|
29
|
+
MODEL = 'resourceUseNotRelevant'
|
30
|
+
TIER = IndicatorMethodTier.NOT_RELEVANT.value
|
31
|
+
|
32
|
+
|
33
|
+
def _indicator(term_id: str, land_cover_id: str):
|
34
|
+
indicator = _new_indicator(term_id, MODEL, land_cover_id)
|
35
|
+
indicator['value'] = 0
|
36
|
+
indicator['methodTier'] = TIER
|
37
|
+
return indicator
|
38
|
+
|
39
|
+
|
40
|
+
def _resourceUse_ids():
|
41
|
+
return lookup_term_ids(download_lookup(f"{TermTermType.RESOURCEUSE.value}.csv"))
|
42
|
+
|
43
|
+
|
44
|
+
def _should_run_resourceUse(impact: dict):
|
45
|
+
def run(term_id: str):
|
46
|
+
is_not_relevant = not _run_required(MODEL, term_id, impact.get('cycle', {}))
|
47
|
+
in_system_boundary = is_in_system_boundary(term_id)
|
48
|
+
|
49
|
+
should_run = all([is_not_relevant, in_system_boundary])
|
50
|
+
if should_run:
|
51
|
+
# no need to show the model failed
|
52
|
+
logRequirements(impact, model=MODEL, term=term_id,
|
53
|
+
is_not_relevant=is_not_relevant,
|
54
|
+
in_system_boundary=in_system_boundary,
|
55
|
+
run_required=False)
|
56
|
+
logShouldRun(impact, MODEL, term_id, should_run)
|
57
|
+
return should_run
|
58
|
+
return run
|
59
|
+
|
60
|
+
|
61
|
+
def run(_, impact: dict):
|
62
|
+
term_ids = _resourceUse_ids()
|
63
|
+
term_ids = list(filter(_should_run_resourceUse(impact), term_ids))
|
64
|
+
land_cover_term_id = get_land_cover_term_id(get_site(impact).get('siteType'))
|
65
|
+
return [_indicator(term_id, land_cover_term_id) for term_id in term_ids]
|
@@ -80,7 +80,7 @@ def _should_run(cycle: dict):
|
|
80
80
|
measurements = site.get('measurements', [])
|
81
81
|
|
82
82
|
def _get_measurement_content(term_id: str):
|
83
|
-
return most_relevant_measurement_value(measurements, term_id, end_date)
|
83
|
+
return most_relevant_measurement_value(measurements, term_id, end_date, default=None)
|
84
84
|
|
85
85
|
nla_environment = _get_measurement_content('nutrientLossToAquaticEnvironment')
|
86
86
|
soil_nitrogen_content = _get_measurement_content('totalNitrogenPerKgSoil')
|
@@ -91,6 +91,7 @@ def _should_run(cycle: dict):
|
|
91
91
|
|
92
92
|
precipitation = _get_measurement_content('precipitationAnnual')
|
93
93
|
inputs_water = get_water_input(cycle)
|
94
|
+
total_water = list_sum([(inputs_water or 0)/10, precipitation or 0])
|
94
95
|
|
95
96
|
practice_factor = get_practice_factor(TERM_ID, site)
|
96
97
|
pcorr = get_pcorr(slope / 100) if slope is not None else None
|
@@ -100,7 +101,7 @@ def _should_run(cycle: dict):
|
|
100
101
|
list_of_contents_for_A = [
|
101
102
|
practice_factor, erodibility, slope_length,
|
102
103
|
pcorr, p_ef_c1, ef_p_c2]
|
103
|
-
list_of_contents_for_R = [heavy_winter_precipitation,
|
104
|
+
list_of_contents_for_R = [heavy_winter_precipitation, total_water]
|
104
105
|
list_of_contents_for_value = [nla_environment, soil_nitrogen_content]
|
105
106
|
|
106
107
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
@@ -118,8 +119,9 @@ def _should_run(cycle: dict):
|
|
118
119
|
soil_nitrogen_content=soil_nitrogen_content)
|
119
120
|
|
120
121
|
should_run = all([
|
122
|
+
heavy_winter_precipitation is not None,
|
123
|
+
total_water > 0,
|
121
124
|
all(list_of_contents_for_A),
|
122
|
-
all(list_of_contents_for_R),
|
123
125
|
all(list_of_contents_for_value)
|
124
126
|
])
|
125
127
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
@@ -80,7 +80,7 @@ def _should_run(cycle: dict):
|
|
80
80
|
measurements = site.get('measurements', [])
|
81
81
|
|
82
82
|
def _get_measurement_content(term_id: str):
|
83
|
-
return most_relevant_measurement_value(measurements, term_id, end_date)
|
83
|
+
return most_relevant_measurement_value(measurements, term_id, end_date, default=None)
|
84
84
|
|
85
85
|
nla_environment = _get_measurement_content('nutrientLossToAquaticEnvironment')
|
86
86
|
soil_phosphorus_content = _get_measurement_content('totalPhosphorusPerKgSoil')
|
@@ -91,6 +91,7 @@ def _should_run(cycle: dict):
|
|
91
91
|
|
92
92
|
precipitation = _get_measurement_content('precipitationAnnual')
|
93
93
|
inputs_water = get_water_input(cycle)
|
94
|
+
total_water = list_sum([(inputs_water or 0)/10, precipitation or 0])
|
94
95
|
|
95
96
|
practice_factor = get_practice_factor(TERM_ID, site)
|
96
97
|
pcorr = get_pcorr(slope / 100) if slope is not None else None
|
@@ -100,7 +101,7 @@ def _should_run(cycle: dict):
|
|
100
101
|
list_of_contents_for_A = [
|
101
102
|
practice_factor, erodibility, slope_length,
|
102
103
|
pcorr, p_ef_c1, ef_p_c2]
|
103
|
-
list_of_contents_for_R = [heavy_winter_precipitation,
|
104
|
+
list_of_contents_for_R = [heavy_winter_precipitation, total_water]
|
104
105
|
list_of_contents_for_value = [nla_environment, soil_phosphorus_content]
|
105
106
|
|
106
107
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
@@ -118,8 +119,9 @@ def _should_run(cycle: dict):
|
|
118
119
|
soil_phosphorus_content=soil_phosphorus_content)
|
119
120
|
|
120
121
|
should_run = all([
|
122
|
+
heavy_winter_precipitation is not None,
|
123
|
+
total_water > 0,
|
121
124
|
all(list_of_contents_for_A),
|
122
|
-
all(list_of_contents_for_R),
|
123
125
|
all(list_of_contents_for_value)
|
124
126
|
])
|
125
127
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
@@ -43,25 +43,26 @@ def get_pcorr(slope: float):
|
|
43
43
|
|
44
44
|
|
45
45
|
def _get_C2_factor(term_id: str, term: dict):
|
46
|
-
return safe_parse_float(get_lookup_value(term, 'C2_FACTORS', model=MODEL, term=term_id), None)
|
46
|
+
return safe_parse_float(get_lookup_value(term, 'C2_FACTORS', model=MODEL, term=term_id), default=None)
|
47
47
|
|
48
48
|
|
49
49
|
def get_practice_factor(term_id: str, site: dict):
|
50
50
|
return safe_parse_float(
|
51
|
-
get_lookup_value(site.get('country', {}), 'Practice_Factor', model=MODEL, term=term_id), None)
|
51
|
+
get_lookup_value(site.get('country', {}), 'Practice_Factor', model=MODEL, term=term_id), default=None)
|
52
52
|
|
53
53
|
|
54
54
|
def get_p_ef_c1(term_id: str, cycle: dict):
|
55
55
|
primary_product = find_primary_product(cycle) or {}
|
56
56
|
return safe_parse_float(
|
57
|
-
get_lookup_value(primary_product.get('term', {}), 'P_EF_C1', model=MODEL, term=term_id), None)
|
57
|
+
get_lookup_value(primary_product.get('term', {}), 'P_EF_C1', model=MODEL, term=term_id), default=None)
|
58
58
|
|
59
59
|
|
60
60
|
def get_ef_p_c2(term_id: str, cycle: dict):
|
61
61
|
tillage = _get_tillage(cycle)
|
62
62
|
country = cycle.get('site', {}).get('country', {})
|
63
63
|
return _get_C2_factor(term_id, tillage) if tillage else safe_parse_float(
|
64
|
-
get_lookup_value(country, 'EF_P_C2', model=MODEL, term=term_id), None
|
64
|
+
get_lookup_value(country, 'EF_P_C2', model=MODEL, term=term_id), default=None
|
65
|
+
)
|
65
66
|
|
66
67
|
|
67
68
|
def get_water_input(cycle: dict):
|
@@ -150,7 +150,7 @@ def _get_value(cycle: dict, content_list_of_items: list, N_total: float, term=TE
|
|
150
150
|
sand_factor = _sand_factor(sand, clay)
|
151
151
|
eco_factor = get_ecoClimateZone_lookup_value(ecoClimateZone, 'STEHFEST_BOUWMAN_2006_N2O-N_FACTOR')
|
152
152
|
crop_grouping_factor = N2O_FACTORS_BY_CROP[crop_grouping]
|
153
|
-
sum_factors = sum([carbon_factor, soil_factor, sand_factor, eco_factor, crop_grouping_factor])
|
153
|
+
sum_factors = sum([carbon_factor, soil_factor, sand_factor, eco_factor or 0, crop_grouping_factor])
|
154
154
|
conversion_unit = get_atomic_conversion(Units.KG_N2O, Units.TO_N)
|
155
155
|
|
156
156
|
try:
|
@@ -85,10 +85,10 @@ def _should_run(cycle: dict, term=TERM_ID, tier=TIER):
|
|
85
85
|
|
86
86
|
|
87
87
|
def _get_value(cycle: dict, country: dict, N_total: float, term=TERM_ID):
|
88
|
-
|
88
|
+
EF_NOX = safe_parse_float(get_lookup_value(country, LOOKUPS['region'], model=MODEL, term=TERM_ID), default=0)
|
89
89
|
debugValues(cycle, model=MODEL, term=term,
|
90
|
-
|
91
|
-
return
|
90
|
+
EF_NOX=EF_NOX)
|
91
|
+
return EF_NOX * N_total
|
92
92
|
|
93
93
|
|
94
94
|
def _run(cycle: dict, country: dict, N_total: float):
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from hestia_earth.schema import TermTermType
|
2
|
-
from hestia_earth.utils.model import find_term_match
|
2
|
+
from hestia_earth.utils.model import find_term_match, filter_list_term_type
|
3
3
|
from hestia_earth.utils.tools import flatten
|
4
4
|
from hestia_earth.utils.emission import cycle_emissions_in_system_boundary
|
5
5
|
|
@@ -35,8 +35,10 @@ def get_background_inputs(cycle: dict, extra_inputs: list = []):
|
|
35
35
|
return list(filter(_should_run_input(cycle.get('products', [])), inputs))
|
36
36
|
|
37
37
|
|
38
|
-
def no_gap_filled_background_emissions(
|
39
|
-
|
38
|
+
def no_gap_filled_background_emissions(
|
39
|
+
node: dict, list_key: str = 'emissions', term_type: TermTermType = TermTermType.EMISSION
|
40
|
+
):
|
41
|
+
blank_nodes = filter_list_term_type(node.get(list_key, []), term_type)
|
40
42
|
|
41
43
|
def check_input(input: dict):
|
42
44
|
input_term_id = input.get('term', {}).get('@id')
|
@@ -44,12 +46,12 @@ def no_gap_filled_background_emissions(cycle: dict):
|
|
44
46
|
animal_term_id = input.get('animal', {}).get('@id')
|
45
47
|
|
46
48
|
return not any([
|
47
|
-
is_from_model(
|
48
|
-
for
|
49
|
+
is_from_model(blank_node)
|
50
|
+
for blank_node in blank_nodes
|
49
51
|
if all([
|
50
|
-
any([i.get('@id') == input_term_id for i in
|
51
|
-
|
52
|
-
|
52
|
+
any([i.get('@id') == input_term_id for i in blank_node.get('inputs', [])]),
|
53
|
+
blank_node.get('operation', {}).get('@id') == operation_term_id,
|
54
|
+
blank_node.get('animal', {}).get('@id') == animal_term_id
|
53
55
|
])
|
54
56
|
])
|
55
57
|
|
@@ -67,10 +69,12 @@ def all_background_emission_term_ids(cycle: dict):
|
|
67
69
|
def log_missing_emissions(cycle: dict, **log_args):
|
68
70
|
all_emission_term_ids = all_background_emission_term_ids(cycle)
|
69
71
|
|
70
|
-
def log_input(input_term_id: str, included_emission_term_ids: list):
|
72
|
+
def log_input(input_term_id: str, included_emission_term_ids: list, **extra_log_args):
|
71
73
|
missing_emission_term_ids = [
|
72
74
|
term_id for term_id in all_emission_term_ids if term_id not in included_emission_term_ids
|
73
75
|
]
|
74
76
|
for emission_id in missing_emission_term_ids:
|
75
|
-
logShouldRun(cycle, term=input_term_id, should_run=False, emission_id=emission_id,
|
77
|
+
logShouldRun(cycle, term=input_term_id, should_run=False, emission_id=emission_id,
|
78
|
+
**log_args,
|
79
|
+
**extra_log_args)
|
76
80
|
return log_input
|
@@ -159,7 +159,7 @@ def _run_required(model: str, term_id: str, data: dict):
|
|
159
159
|
input_id_allowed=input_id_allowed,
|
160
160
|
input_termType_allowed=input_termType_allowed)
|
161
161
|
# logging this for the model would cause issues parsing statuses
|
162
|
-
if model
|
162
|
+
if not model.endswith('NotRelevant'):
|
163
163
|
debugValues(data, model=model, term=term_id, run_required=run_required)
|
164
164
|
return run_required
|
165
165
|
|
@@ -1326,16 +1326,18 @@ def get_inputs_from_properties(input: dict, term_types: Union[TermTermType, List
|
|
1326
1326
|
dict
|
1327
1327
|
A dictionary of nodes grouped by latest date, in the format `{date: list[node]}`.
|
1328
1328
|
"""
|
1329
|
+
term = input.get('term', {})
|
1329
1330
|
input_value = list_sum(input.get('value', []))
|
1330
1331
|
properties = (
|
1331
1332
|
input.get('properties') or
|
1332
|
-
|
1333
|
-
download_term(
|
1333
|
+
term.get('defaultProperties') or
|
1334
|
+
download_term(term).get('defaultProperties')
|
1334
1335
|
)
|
1335
1336
|
inputs = non_empty_list([
|
1336
1337
|
{
|
1337
1338
|
'term': p.get('key'),
|
1338
|
-
'value': [(p.get('value') / 100) * (p.get('share', 100) / 100) * input_value]
|
1339
|
+
'value': [(p.get('value') / 100) * (p.get('share', 100) / 100) * input_value],
|
1340
|
+
'parent': term
|
1339
1341
|
} for p in (properties or []) if all([p.get('key'), p.get('value')])
|
1340
1342
|
]) if input_value > 0 else []
|
1341
1343
|
return filter_list_term_type(inputs, term_types)
|
@@ -30,7 +30,7 @@ def get_N2ON_fertiliser_coeff_from_primary_product(model: str, log_id: str, cycl
|
|
30
30
|
product = find_primary_product(cycle)
|
31
31
|
term_id = product.get('term', {}).get('@id') if product else None
|
32
32
|
percent = get_crop_lookup_value(model, log_id, term_id, 'N2ON_FERT') if term_id else None
|
33
|
-
return safe_parse_float(percent, 0.01)
|
33
|
+
return safe_parse_float(percent, default=0.01)
|
34
34
|
|
35
35
|
|
36
36
|
def is_plantation(model: str, log_id: str, term_id: str):
|
@@ -1,3 +1,9 @@
|
|
1
|
+
from hestia_earth.schema import TermTermType
|
2
|
+
from hestia_earth.utils.model import find_term_match
|
3
|
+
from hestia_earth.utils.tools import flatten
|
4
|
+
|
5
|
+
from .completeness import _is_term_type_complete
|
6
|
+
|
1
7
|
PRODUCT_ID_TO_PRACTICES_ID = [
|
2
8
|
{'product': 'aboveGroundCropResidueRemoved', 'practices': ['residueRemoved']},
|
3
9
|
{'product': 'aboveGroundCropResidueIncorporated', 'practices': [
|
@@ -11,3 +17,13 @@ PRODUCT_ID_TO_PRACTICES_ID = [
|
|
11
17
|
|
12
18
|
|
13
19
|
def crop_residue_product_ids(): return [v.get('product') for v in PRODUCT_ID_TO_PRACTICES_ID]
|
20
|
+
|
21
|
+
|
22
|
+
def get_crop_residue_burnt_value(cycle: dict):
|
23
|
+
products = cycle.get('products', [])
|
24
|
+
value = flatten([
|
25
|
+
find_term_match(products, 'aboveGroundCropResidueBurnt').get('value', []),
|
26
|
+
find_term_match(products, 'discardedCropBurnt').get('value', [])
|
27
|
+
])
|
28
|
+
data_complete = _is_term_type_complete(cycle, TermTermType.CROPRESIDUE)
|
29
|
+
return [0] if len(value) == 0 and data_complete else value
|
@@ -204,7 +204,7 @@ def get_inorganic_fertiliser_P_total(cycle: dict) -> float:
|
|
204
204
|
|
205
205
|
def get_max_rooting_depth(cycle: dict) -> float:
|
206
206
|
properties = list(map(lambda p: get_node_property(p, 'rootingDepth'), cycle.get('products', [])))
|
207
|
-
values = [safe_parse_float(p.get('value')) for p in properties if p.get('value') is not None]
|
207
|
+
values = [safe_parse_float(p.get('value'), default=0) for p in properties if p.get('value') is not None]
|
208
208
|
return max(values) if len(values) > 0 else None
|
209
209
|
|
210
210
|
|
@@ -87,7 +87,7 @@ def get_ecoClimateZone_lookup_value(eco_climate_zone: str, col_name: str, group_
|
|
87
87
|
code = int(str(eco_climate_zone))
|
88
88
|
data = _get_single_table_value(lookup, column_name('ecoClimateZone'), code, column_name(col_name))
|
89
89
|
return safe_parse_float(
|
90
|
-
data if group_name is None else extract_grouped_data(data, group_name)
|
90
|
+
data if group_name is None else extract_grouped_data(data, group_name), default=None
|
91
91
|
)
|
92
92
|
except Exception:
|
93
93
|
return 0
|
@@ -118,7 +118,7 @@ def get_ecoClimateZone_lookup_grouped_value(
|
|
118
118
|
code = int(str(eco_climate_zone))
|
119
119
|
data = _get_single_table_value(lookup, column_name('ecoClimateZone'), code, column_name(col_name))
|
120
120
|
grouped_data = reduce(
|
121
|
-
lambda prev, curr: prev | {curr.split(':')[0]: safe_parse_float(curr.split(':')[1])},
|
121
|
+
lambda prev, curr: prev | {curr.split(':')[0]: safe_parse_float(curr.split(':')[1], default=None)},
|
122
122
|
data.split(';'),
|
123
123
|
{}
|
124
124
|
) if data is not None and isinstance(data, str) and len(data) > 1 else default
|
@@ -19,7 +19,7 @@ def _get_nh3_factor(lookup_name: str, term_id: str, input: dict, **log_args):
|
|
19
19
|
input_term_id = input.get('term', {}).get('@id')
|
20
20
|
value = get_table_value(download_lookup(lookup_name), 'termid', term_id, column_name(input_term_id))
|
21
21
|
debugMissingLookup(lookup_name, 'termid', term_id, input_term_id, value, **log_args)
|
22
|
-
return safe_parse_float(value, None)
|
22
|
+
return safe_parse_float(value, default=None)
|
23
23
|
|
24
24
|
|
25
25
|
def get_excreta_inputs_with_factor(cycle: dict, lookup_name: str, excreta_conversion_func, **log_args):
|
@@ -27,9 +27,9 @@ def _should_rescale_by_dm(property_id: str):
|
|
27
27
|
def _dm_property(term_id: str, property_values: dict, dm_property_values: dict, dry_matter_property: dict):
|
28
28
|
blank_node_data = {}
|
29
29
|
for property_key in property_values.keys():
|
30
|
-
new_dm_value = safe_parse_float(dry_matter_property.get(property_key))
|
31
|
-
old_dm_value = safe_parse_float(dm_property_values.get(property_key))
|
32
|
-
old_property_value = safe_parse_float(property_values.get(property_key))
|
30
|
+
new_dm_value = safe_parse_float(dry_matter_property.get(property_key), default=None)
|
31
|
+
old_dm_value = safe_parse_float(dm_property_values.get(property_key), default=None)
|
32
|
+
old_property_value = safe_parse_float(property_values.get(property_key), default=None)
|
33
33
|
if all([new_dm_value, old_dm_value, old_property_value]):
|
34
34
|
new_value = round(
|
35
35
|
old_property_value / old_dm_value * new_dm_value,
|
@@ -5,7 +5,13 @@ from hestia_earth.utils.tools import flatten
|
|
5
5
|
|
6
6
|
from .blank_node import get_inputs_from_properties
|
7
7
|
|
8
|
-
_TERM_TYPES = [
|
8
|
+
_TERM_TYPES = [
|
9
|
+
TermTermType.INORGANICFERTILISER,
|
10
|
+
TermTermType.ORGANICFERTILISER,
|
11
|
+
TermTermType.OTHERINORGANICCHEMICAL,
|
12
|
+
TermTermType.OTHERORGANICCHEMICAL,
|
13
|
+
TermTermType.PESTICIDEAI
|
14
|
+
]
|
9
15
|
|
10
16
|
|
11
17
|
def get_fertilisers_from_inputs(cycle: dict, term_types: Union[TermTermType, List[TermTermType]] = _TERM_TYPES):
|
@@ -31,12 +31,12 @@ def get_NH3_emission_factor(term_id: str, soilPh: float, temperature: float):
|
|
31
31
|
soilPh_key = _get_soilPh_lookup_key(soilPh)
|
32
32
|
temperature_key = _get_temperature_lookup_key(temperature)
|
33
33
|
data = get_term_lookup(term_id, f"NH3_emissions_factor_{soilPh_key}")
|
34
|
-
return safe_parse_float(extract_grouped_data(data, temperature_key), None)
|
34
|
+
return safe_parse_float(extract_grouped_data(data, temperature_key), default=None)
|
35
35
|
|
36
36
|
|
37
37
|
def get_country_breakdown(model: str, term_id: str, country_id: str, col_name: str):
|
38
38
|
value = get_region_lookup_value(BREAKDOWN_LOOKUP, country_id, col_name, model=model, term=term_id)
|
39
|
-
return safe_parse_float(value, None)
|
39
|
+
return safe_parse_float(value, default=None)
|
40
40
|
|
41
41
|
|
42
42
|
def get_cycle_inputs(cycle: dict):
|
@@ -4,7 +4,7 @@ from hestia_earth.utils.tools import list_sum, non_empty_list, list_average, fla
|
|
4
4
|
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
|
5
5
|
|
6
6
|
from hestia_earth.models.log import logger
|
7
|
-
from . import _filter_list_term_unit, _load_calculated_node
|
7
|
+
from . import _filter_list_term_unit, _load_calculated_node, group_by
|
8
8
|
from .constant import Units
|
9
9
|
from .blank_node import get_total_value, get_total_value_converted, get_lookup_value
|
10
10
|
from .term import download_term
|
@@ -148,3 +148,36 @@ def total_excreta(inputs: list, units=Units.KG_N):
|
|
148
148
|
def get_total_irrigation_m3(cycle: dict):
|
149
149
|
irrigation_inputs = filter_list_term_type(cycle.get('inputs', []), TermTermType.WATER)
|
150
150
|
return sum([list_average(i.get('value')) for i in irrigation_inputs if len(i.get('value', [])) > 0])
|
151
|
+
|
152
|
+
|
153
|
+
def _group_inputs(inputs: list):
|
154
|
+
grouped_inputs = group_by(inputs, ['input.term.@id'])
|
155
|
+
return [
|
156
|
+
inputs[0] | {'value': list_sum(flatten([v.get('input-value') for v in inputs]))}
|
157
|
+
for inputs in grouped_inputs.values()
|
158
|
+
]
|
159
|
+
|
160
|
+
|
161
|
+
def _input_data(input: dict):
|
162
|
+
return {
|
163
|
+
'input': input,
|
164
|
+
'input-value': list_sum(input.get('value'), default=None),
|
165
|
+
'has-linked-impact-assessment': bool(input.get('impactAssessment')),
|
166
|
+
'is-fromCycle': input.get('fromCycle', False),
|
167
|
+
'is-producedInCycle': input.get('producedInCycle', False)
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
def unique_background_inputs(cycle: dict):
|
172
|
+
inputs = non_empty_list(map(_input_data, cycle.get('inputs', [])))
|
173
|
+
|
174
|
+
# sum up inputs with the same id
|
175
|
+
return _group_inputs([
|
176
|
+
v for v in inputs
|
177
|
+
if all([
|
178
|
+
v.get('input-value') or -1 > 0,
|
179
|
+
not v.get('has-linked-impact-assessment'),
|
180
|
+
not v.get('is-fromCycle'),
|
181
|
+
not v.get('is-producedInCycle')
|
182
|
+
])
|
183
|
+
])
|
@@ -33,8 +33,8 @@ def get_default_digestibility(model: str, term_id: str, cycle: dict):
|
|
33
33
|
lookup_col = column_name(product_id)
|
34
34
|
value = get_table_value(lookup, 'termid', system_id, lookup_col)
|
35
35
|
debugMissingLookup(lookup_name, 'termid', term_id, lookup_col, value, model=model, term=term_id)
|
36
|
-
min = safe_parse_float(extract_grouped_data(value, 'min'), None)
|
37
|
-
max = safe_parse_float(extract_grouped_data(value, 'max'), None)
|
36
|
+
min = safe_parse_float(extract_grouped_data(value, 'min'), default=None)
|
37
|
+
max = safe_parse_float(extract_grouped_data(value, 'max'), default=None)
|
38
38
|
if min and max:
|
39
39
|
return mean([min, max])
|
40
40
|
|
@@ -28,7 +28,7 @@ def _factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, g
|
|
28
28
|
coefficient = safe_parse_float(
|
29
29
|
extract_grouped_data(coefficient, grouped_data_key),
|
30
30
|
default=None
|
31
|
-
) if ':' in str(coefficient) else safe_parse_float(coefficient, None)
|
31
|
+
) if ':' in str(coefficient) else safe_parse_float(coefficient, default=None)
|
32
32
|
if value is not None and coefficient is not None:
|
33
33
|
if model:
|
34
34
|
debugValues(data, model=model, term=term_id,
|
@@ -32,17 +32,18 @@ def _new_measurement(term, method=None):
|
|
32
32
|
return include_method(node, term_id=method)
|
33
33
|
|
34
34
|
|
35
|
-
def measurement_value(measurement: dict, is_larger_unit: bool = False) -> float:
|
35
|
+
def measurement_value(measurement: dict, is_larger_unit: bool = False, default=None) -> float:
|
36
36
|
term = measurement.get('term', {})
|
37
37
|
reducer = get_lookup_value(term, 'arrayTreatmentLargerUnitOfTime' if is_larger_unit else 'arrayTreatment') or 'mean'
|
38
38
|
value = non_empty_list(measurement.get('value', []))
|
39
39
|
is_value_valid = value is not None and isinstance(value, list) and len(value) > 0
|
40
|
-
|
40
|
+
print(reducer, value, is_value_valid)
|
41
|
+
return MEASUREMENT_REDUCE.get(reducer, lambda v: v[0])(value) if is_value_valid else default
|
41
42
|
|
42
43
|
|
43
44
|
def most_relevant_measurement_value(measurements: list, term_id: str, date: str, default=None):
|
44
45
|
measurement = most_relevant_blank_node_by_id(measurements, term_id, date)
|
45
|
-
return measurement_value(measurement) if measurement else default
|
46
|
+
return measurement_value(measurement, default=default) if measurement else default
|
46
47
|
|
47
48
|
|
48
49
|
def _group_measurement_key(measurement: dict, include_dates: bool = True):
|
@@ -167,7 +168,7 @@ def most_relevant_measurement_value_by_depth_and_date(
|
|
167
168
|
|
168
169
|
def depth_distance(depth_string):
|
169
170
|
split = depth_string.split('_')
|
170
|
-
upper, lower = safe_parse_float(split[0]), safe_parse_float(split[2]) # "a_to_b"
|
171
|
+
upper, lower = safe_parse_float(split[0], default=0), safe_parse_float(split[2], default=0) # "a_to_b"
|
171
172
|
return abs(upper - depth_upper) + abs(lower - depth_lower)
|
172
173
|
|
173
174
|
nearest_key = min(grouped_measurements.keys(), key=depth_distance)
|
@@ -17,5 +17,5 @@ PRODUCTIVITY_KEY = {
|
|
17
17
|
|
18
18
|
|
19
19
|
def get_productivity(country: dict, default: PRODUCTIVITY = PRODUCTIVITY.HIGH):
|
20
|
-
hdi = safe_parse_float(get_lookup_value(country, 'hdi'), None)
|
20
|
+
hdi = safe_parse_float(get_lookup_value(country, 'hdi'), default=None)
|
21
21
|
return next((key for key in PRODUCTIVITY_KEY if hdi and PRODUCTIVITY_KEY[key](hdi)), default)
|
@@ -132,9 +132,11 @@ def get_node_property_value_converted(model: str, node: dict, prop_id: str, defa
|
|
132
132
|
|
133
133
|
def _get_nitrogen_content(node: dict):
|
134
134
|
return safe_parse_float(
|
135
|
-
get_node_property(node, 'nitrogenContent').get('value', 0)
|
135
|
+
get_node_property(node, 'nitrogenContent').get('value', 0), default=0
|
136
|
+
) if node else 0
|
136
137
|
|
137
138
|
|
138
139
|
def _get_nitrogen_tan_content(node: dict):
|
139
140
|
return safe_parse_float(
|
140
|
-
get_node_property(node, 'totalAmmoniacalNitrogenContentAsN').get('value', 0)
|
141
|
+
get_node_property(node, 'totalAmmoniacalNitrogenContentAsN').get('value', 0), default=0
|
142
|
+
) if node else 0
|