hestia-earth-models 0.58.0__py3-none-any.whl → 0.59.1__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (35) hide show
  1. hestia_earth/models/cycle/{irrigated.py → irrigatedTypeUnspecified.py} +4 -4
  2. hestia_earth/models/cycle/residueIncorporated.py +1 -1
  3. hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +2 -2
  4. hestia_earth/models/geospatialDatabase/clayContent.py +17 -4
  5. hestia_earth/models/geospatialDatabase/sandContent.py +17 -4
  6. hestia_earth/models/impact_assessment/irrigated.py +0 -3
  7. hestia_earth/models/ipcc2019/co2ToAirSoilCarbonStockChangeManagementChange.py +10 -9
  8. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +4 -51
  9. hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +104 -0
  10. hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserDirect.py +105 -0
  11. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +1059 -1220
  12. hestia_earth/models/ipcc2019/utils.py +82 -1
  13. hestia_earth/models/mocking/search-results.json +165 -95
  14. hestia_earth/models/site/management.py +12 -9
  15. hestia_earth/models/site/organicCarbonPerHa.py +251 -89
  16. hestia_earth/models/utils/blank_node.py +157 -34
  17. hestia_earth/models/utils/cycle.py +6 -3
  18. hestia_earth/models/utils/measurement.py +1 -1
  19. hestia_earth/models/utils/site.py +1 -1
  20. hestia_earth/models/utils/term.py +46 -1
  21. hestia_earth/models/version.py +1 -1
  22. {hestia_earth_models-0.58.0.dist-info → hestia_earth_models-0.59.1.dist-info}/METADATA +4 -8
  23. {hestia_earth_models-0.58.0.dist-info → hestia_earth_models-0.59.1.dist-info}/RECORD +35 -31
  24. tests/models/cycle/{test_irrigated.py → test_irrigatedTypeUnspecified.py} +1 -1
  25. tests/models/geospatialDatabase/test_clayContent.py +9 -3
  26. tests/models/geospatialDatabase/test_sandContent.py +9 -3
  27. tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py +74 -0
  28. tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py +74 -0
  29. tests/models/ipcc2019/test_organicCarbonPerHa.py +303 -1044
  30. tests/models/site/test_organicCarbonPerHa.py +51 -5
  31. tests/models/utils/test_blank_node.py +102 -42
  32. tests/models/utils/test_term.py +17 -3
  33. {hestia_earth_models-0.58.0.dist-info → hestia_earth_models-0.59.1.dist-info}/LICENSE +0 -0
  34. {hestia_earth_models-0.58.0.dist-info → hestia_earth_models-0.59.1.dist-info}/WHEEL +0 -0
  35. {hestia_earth_models-0.58.0.dist-info → hestia_earth_models-0.59.1.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
- from hestia_earth.utils.model import find_term_match
1
+ from hestia_earth.schema import TermTermType
2
+ from hestia_earth.utils.model import find_term_match, filter_list_term_type
2
3
  from hestia_earth.utils.tools import safe_parse_float
3
4
 
4
5
  from hestia_earth.models.log import debugValues
@@ -7,6 +8,7 @@ from hestia_earth.models.utils.cycle import get_ecoClimateZone
7
8
  from hestia_earth.models.utils.constant import Units, get_atomic_conversion
8
9
  from hestia_earth.models.utils.blank_node import find_terms_value
9
10
  from hestia_earth.models.utils.term import get_lookup_value, get_milkYield_terms
11
+ from hestia_earth.models.utils.ecoClimateZone import get_ecoClimateZone_lookup_value
10
12
  from . import MODEL
11
13
 
12
14
  # From IPCC2019 Indirect N2O emission factor, in N [avg, min, max, std]
@@ -89,3 +91,82 @@ def check_consecutive(ints: list[int]) -> bool:
89
91
  """
90
92
  range_list = list(range(min(ints), max(ints)+1)) if ints else []
91
93
  return all(a == b for a, b in zip(ints, range_list))
94
+
95
+
96
+ N2O_FACTORS = {
97
+ # All N inputs in dry climate
98
+ 'dry': {
99
+ 'value': 0.005,
100
+ 'min': 0,
101
+ 'max': 0.011
102
+ },
103
+ 'wet': {
104
+ # Synthetic fertiliser inputs in wet climate
105
+ TermTermType.INORGANICFERTILISER: {
106
+ 'value': 0.016,
107
+ 'min': 0.013,
108
+ 'max': 0.019
109
+ },
110
+ # Other N inputs in wet climate
111
+ TermTermType.ORGANICFERTILISER: {
112
+ 'value': 0.006,
113
+ 'min': 0.001,
114
+ 'max': 0.011
115
+ },
116
+ TermTermType.CROPRESIDUE: {
117
+ 'value': 0.006,
118
+ 'min': 0.001,
119
+ 'max': 0.011
120
+ }
121
+ },
122
+ 'default': {
123
+ 'value': 0.01,
124
+ 'min': 0.001,
125
+ 'max': 0.018
126
+ },
127
+ 'flooded_rice': {
128
+ 'value': 0.004,
129
+ 'min': 0,
130
+ 'max': 0.029
131
+ }
132
+ }
133
+
134
+
135
+ def _get_waterRegime_lookup(model_term_id: str, practice: dict, col: str):
136
+ return safe_parse_float(get_lookup_value(practice.get('term', {}), col, model=MODEL, term=model_term_id), None)
137
+
138
+
139
+ def _is_wet(ecoClimateZone: str = None):
140
+ return get_ecoClimateZone_lookup_value(ecoClimateZone, 'wet') == 1 if ecoClimateZone else None
141
+
142
+
143
+ def _ecoClimate_factors(input_term_type: TermTermType, ecoClimateZone: str = None):
144
+ is_wet = _is_wet(ecoClimateZone)
145
+ factors_key = 'default' if is_wet is None else 'wet' if is_wet else 'dry'
146
+ factors = N2O_FACTORS[factors_key]
147
+ return (factors.get(input_term_type) if factors_key == 'wet' else factors, is_wet is None)
148
+
149
+
150
+ def _flooded_rice_factors(model_term_id: str, cycle: dict):
151
+ lookup_name = 'IPCC_2019_N2O_rice'
152
+ practices = filter_list_term_type(cycle.get('practices', []), TermTermType.WATERREGIME)
153
+ practice = next((p for p in practices if _get_waterRegime_lookup(model_term_id, p, lookup_name) is not None), None)
154
+
155
+ factors = {
156
+ 'value': _get_waterRegime_lookup(model_term_id, practice, lookup_name),
157
+ 'min': _get_waterRegime_lookup(model_term_id, practice, lookup_name + '-min'),
158
+ 'max': _get_waterRegime_lookup(model_term_id, practice, lookup_name + '-max')
159
+ } if practice else N2O_FACTORS['flooded_rice']
160
+
161
+ return (factors, practice is None)
162
+
163
+
164
+ def get_N2O_factors(
165
+ model_term_id: str,
166
+ cycle: dict,
167
+ input_term_type: TermTermType,
168
+ ecoClimateZone: str = None,
169
+ flooded_rice: bool = False
170
+ ):
171
+ return _flooded_rice_factors(model_term_id, cycle) if flooded_rice \
172
+ else _ecoClimate_factors(input_term_type, ecoClimateZone)
@@ -839,11 +839,11 @@
839
839
  },
840
840
  {
841
841
  "@type": "Term",
842
- "@id": "longFallowCrop"
842
+ "@id": "shortFallowCrop"
843
843
  },
844
844
  {
845
845
  "@type": "Term",
846
- "@id": "shortFallowCrop"
846
+ "@id": "longFallowCrop"
847
847
  }
848
848
  ]
849
849
  },
@@ -912,10 +912,6 @@
912
912
  "termType.keyword": "cropResidueManagement"
913
913
  },
914
914
  "results": [
915
- {
916
- "@type": "Term",
917
- "@id": "residueIncorporatedLessThan30DaysBeforeCultivation"
918
- },
919
915
  {
920
916
  "@type": "Term",
921
917
  "@id": "residueRemoved"
@@ -928,6 +924,10 @@
928
924
  "@type": "Term",
929
925
  "@id": "residueIncorporatedMoreThan30DaysBeforeCultivation"
930
926
  },
927
+ {
928
+ "@type": "Term",
929
+ "@id": "residueIncorporatedLessThan30DaysBeforeCultivation"
930
+ },
931
931
  {
932
932
  "@type": "Term",
933
933
  "@id": "pastureRenewed"
@@ -970,27 +970,27 @@
970
970
  },
971
971
  {
972
972
  "@type": "Term",
973
- "@id": "aboveGroundCropResidueBurnt"
973
+ "@id": "discardedCropRemoved"
974
974
  },
975
975
  {
976
976
  "@type": "Term",
977
- "@id": "belowGroundCropResidue"
977
+ "@id": "aboveGroundCropResidueTotal"
978
978
  },
979
979
  {
980
980
  "@type": "Term",
981
- "@id": "aboveGroundCropResidueLeftOnField"
981
+ "@id": "aboveGroundCropResidueIncorporated"
982
982
  },
983
983
  {
984
984
  "@type": "Term",
985
- "@id": "discardedCropRemoved"
985
+ "@id": "aboveGroundCropResidueBurnt"
986
986
  },
987
987
  {
988
988
  "@type": "Term",
989
- "@id": "aboveGroundCropResidueTotal"
989
+ "@id": "belowGroundCropResidue"
990
990
  },
991
991
  {
992
992
  "@type": "Term",
993
- "@id": "aboveGroundCropResidueIncorporated"
993
+ "@id": "aboveGroundCropResidueLeftOnField"
994
994
  }
995
995
  ]
996
996
  },
@@ -1028,11 +1028,11 @@
1028
1028
  },
1029
1029
  {
1030
1030
  "@type": "Term",
1031
- "@id": "digestibleEnergyPigs"
1031
+ "@id": "digestibleEnergySalmonids"
1032
1032
  },
1033
1033
  {
1034
1034
  "@type": "Term",
1035
- "@id": "digestibleEnergySalmonids"
1035
+ "@id": "digestibleEnergyPigs"
1036
1036
  },
1037
1037
  {
1038
1038
  "@type": "Term",
@@ -1109,14 +1109,6 @@
1109
1109
  "units.keyword": "kg N"
1110
1110
  },
1111
1111
  "results": [
1112
- {
1113
- "@type": "Term",
1114
- "@id": "excretaBuffaloKgN"
1115
- },
1116
- {
1117
- "@type": "Term",
1118
- "@id": "excretaSolidAndLiquidFishCrustaceansKgN"
1119
- },
1120
1112
  {
1121
1113
  "@type": "Term",
1122
1114
  "@id": "excretaPoultryKgN"
@@ -1173,6 +1165,14 @@
1173
1165
  "@type": "Term",
1174
1166
  "@id": "processedExcretaKgN"
1175
1167
  },
1168
+ {
1169
+ "@type": "Term",
1170
+ "@id": "excretaBuffaloKgN"
1171
+ },
1172
+ {
1173
+ "@type": "Term",
1174
+ "@id": "excretaSolidAndLiquidFishCrustaceansKgN"
1175
+ },
1176
1176
  {
1177
1177
  "@type": "Term",
1178
1178
  "@id": "excretaDairyCattleKgN"
@@ -1212,47 +1212,47 @@
1212
1212
  },
1213
1213
  {
1214
1214
  "@type": "Term",
1215
- "@id": "excretaLiquidFishCrustaceansKgVs"
1215
+ "@id": "excretaPigsKgVs"
1216
1216
  },
1217
1217
  {
1218
1218
  "@type": "Term",
1219
- "@id": "excretaSolidAndLiquidFishCrustaceansKgVs"
1219
+ "@id": "excretaCamelsKgVs"
1220
1220
  },
1221
1221
  {
1222
1222
  "@type": "Term",
1223
- "@id": "excretaDairyCattleKgVs"
1223
+ "@id": "excretaDucksKgVs"
1224
1224
  },
1225
1225
  {
1226
1226
  "@type": "Term",
1227
- "@id": "excretaGeeseKgVs"
1227
+ "@id": "processedExcretaKgVs"
1228
1228
  },
1229
1229
  {
1230
1230
  "@type": "Term",
1231
- "@id": "excretaPigsKgVs"
1231
+ "@id": "excretaHorsesMulesAndAssesKgVs"
1232
1232
  },
1233
1233
  {
1234
1234
  "@type": "Term",
1235
- "@id": "excretaCamelsKgVs"
1235
+ "@id": "excretaBuffaloKgVs"
1236
1236
  },
1237
1237
  {
1238
1238
  "@type": "Term",
1239
- "@id": "excretaDucksKgVs"
1239
+ "@id": "excretaTurkeysKgVs"
1240
1240
  },
1241
1241
  {
1242
1242
  "@type": "Term",
1243
- "@id": "processedExcretaKgVs"
1243
+ "@id": "excretaLiquidFishCrustaceansKgVs"
1244
1244
  },
1245
1245
  {
1246
1246
  "@type": "Term",
1247
- "@id": "excretaHorsesMulesAndAssesKgVs"
1247
+ "@id": "excretaSolidAndLiquidFishCrustaceansKgVs"
1248
1248
  },
1249
1249
  {
1250
1250
  "@type": "Term",
1251
- "@id": "excretaBuffaloKgVs"
1251
+ "@id": "excretaDairyCattleKgVs"
1252
1252
  },
1253
1253
  {
1254
1254
  "@type": "Term",
1255
- "@id": "excretaTurkeysKgVs"
1255
+ "@id": "excretaGeeseKgVs"
1256
1256
  },
1257
1257
  {
1258
1258
  "@type": "Term",
@@ -1299,7 +1299,7 @@
1299
1299
  "@type": "Term",
1300
1300
  "name": "Generic crop, seed",
1301
1301
  "@id": "genericCropSeed",
1302
- "_score": 24.768406
1302
+ "_score": 23.9092
1303
1303
  }
1304
1304
  ]
1305
1305
  },
@@ -1337,67 +1337,63 @@
1337
1337
  "results": [
1338
1338
  {
1339
1339
  "@type": "Term",
1340
- "@id": "deepWater"
1340
+ "@id": "rainfedDeepWater"
1341
1341
  },
1342
1342
  {
1343
1343
  "@type": "Term",
1344
- "@id": "deepWaterWaterDepth50100Cm"
1344
+ "@id": "rainfedDeepWaterWaterDepth50100Cm"
1345
1345
  },
1346
1346
  {
1347
1347
  "@type": "Term",
1348
- "@id": "deepWaterWaterDepth100Cm"
1348
+ "@id": "rainfedDeepWaterWaterDepth100Cm"
1349
1349
  },
1350
1350
  {
1351
1351
  "@type": "Term",
1352
- "@id": "irrigated"
1352
+ "@id": "irrigatedTypeUnspecified"
1353
1353
  },
1354
1354
  {
1355
1355
  "@type": "Term",
1356
- "@id": "irrigatedManualIrrigation"
1357
- },
1358
- {
1359
- "@type": "Term",
1360
- "@id": "irrigatedSprinklerIrrigation"
1356
+ "@id": "irrigatedLocalizedIrrigation"
1361
1357
  },
1362
1358
  {
1363
1359
  "@type": "Term",
1364
- "@id": "irrigatedDripIrrigation"
1360
+ "@id": "irrigatedFurrowIrrigation"
1365
1361
  },
1366
1362
  {
1367
1363
  "@type": "Term",
1368
- "@id": "irrigatedLocalizedIrrigation"
1364
+ "@id": "irrigatedSubIrrigation"
1369
1365
  },
1370
1366
  {
1371
1367
  "@type": "Term",
1372
- "@id": "irrigatedFurrowIrrigation"
1368
+ "@id": "irrigatedSurfaceIrrigationDrainageRegimeUnspecified"
1373
1369
  },
1374
1370
  {
1375
1371
  "@type": "Term",
1376
- "@id": "irrigatedSubIrrigation"
1372
+ "@id": "irrigatedDripIrrigation"
1377
1373
  },
1378
1374
  {
1379
1375
  "@type": "Term",
1380
- "@id": "irrigatedSurfaceIrrigation"
1376
+ "@id": "irrigatedSprinklerIrrigation"
1381
1377
  },
1382
1378
  {
1383
1379
  "@type": "Term",
1384
- "@id": "irrigatedContinuouslyFlooded"
1380
+ "@id": "irrigatedLateralMoveIrrigation"
1385
1381
  },
1386
1382
  {
1387
1383
  "@type": "Term",
1388
- "@id": "irrigatedLateralMoveIrrigation"
1384
+ "@id": "irrigatedCenterPivotIrrigation"
1389
1385
  },
1390
1386
  {
1391
1387
  "@type": "Term",
1392
- "@id": "irrigatedSingleDrainagePeriod"
1388
+ "@id": "irrigatedSurfaceIrrigationContinuouslyFlooded"
1393
1389
  },
1394
1390
  {
1395
1391
  "@type": "Term",
1396
- "@id": "irrigatedCenterPivotIrrigation"
1392
+ "@id": "irrigatedSurfaceIrrigationMultipleDrainagePeriods"
1397
1393
  },
1398
1394
  {
1399
1395
  "@type": "Term",
1400
- "@id": "irrigatedMultipleDrainagePeriods"
1396
+ "@id": "irrigatedSurfaceIrrigationSingleDrainagePeriod"
1401
1397
  }
1402
1398
  ]
1403
1399
  },
@@ -1536,6 +1532,45 @@
1536
1532
  }
1537
1533
  ]
1538
1534
  },
1535
+ {
1536
+ "name": "get_long_fallow_land_cover_terms",
1537
+ "query": {
1538
+ "bool": {
1539
+ "must": [
1540
+ {
1541
+ "match": {
1542
+ "@type": "Term"
1543
+ }
1544
+ },
1545
+ {
1546
+ "match": {
1547
+ "termType.keyword": "landCover"
1548
+ }
1549
+ },
1550
+ {
1551
+ "match_phrase_prefix": {
1552
+ "name": "long"
1553
+ }
1554
+ },
1555
+ {
1556
+ "match": {
1557
+ "name": "fallow"
1558
+ }
1559
+ }
1560
+ ]
1561
+ }
1562
+ },
1563
+ "results": [
1564
+ {
1565
+ "@type": "Term",
1566
+ "@id": "longFallow"
1567
+ },
1568
+ {
1569
+ "@type": "Term",
1570
+ "@id": "longBareFallow"
1571
+ }
1572
+ ]
1573
+ },
1539
1574
  {
1540
1575
  "name": "get_milkYield_terms",
1541
1576
  "query": {
@@ -1689,7 +1724,48 @@
1689
1724
  ]
1690
1725
  },
1691
1726
  {
1692
- "name": "get_rice_plant_upland_terms",
1727
+ "name": "get_tillage_terms",
1728
+ "query": {
1729
+ "termType.keyword": "tillage",
1730
+ "name": "tillage"
1731
+ },
1732
+ "results": [
1733
+ {
1734
+ "@type": "Term",
1735
+ "@id": "ridgeTillage"
1736
+ },
1737
+ {
1738
+ "@type": "Term",
1739
+ "@id": "noTillage"
1740
+ },
1741
+ {
1742
+ "@type": "Term",
1743
+ "@id": "fullInversionTillage"
1744
+ },
1745
+ {
1746
+ "@type": "Term",
1747
+ "@id": "fullTillage"
1748
+ },
1749
+ {
1750
+ "@type": "Term",
1751
+ "@id": "minimumTillage"
1752
+ },
1753
+ {
1754
+ "@type": "Term",
1755
+ "@id": "deepTillage"
1756
+ },
1757
+ {
1758
+ "@type": "Term",
1759
+ "@id": "mulchTillage"
1760
+ },
1761
+ {
1762
+ "@type": "Term",
1763
+ "@id": "stripTillage"
1764
+ }
1765
+ ]
1766
+ },
1767
+ {
1768
+ "name": "get_upland_rice_crop_terms",
1693
1769
  "query": {
1694
1770
  "bool": {
1695
1771
  "must": [
@@ -1700,12 +1776,12 @@
1700
1776
  },
1701
1777
  {
1702
1778
  "match": {
1703
- "termType.keyword": "landCover"
1779
+ "termType.keyword": "crop"
1704
1780
  }
1705
1781
  },
1706
1782
  {
1707
1783
  "match_phrase": {
1708
- "name": "rice plant"
1784
+ "name": "rice"
1709
1785
  }
1710
1786
  },
1711
1787
  {
@@ -1719,48 +1795,42 @@
1719
1795
  "results": [
1720
1796
  {
1721
1797
  "@type": "Term",
1722
- "@id": "ricePlantUpland"
1798
+ "@id": "riceGrainInHuskUpland"
1723
1799
  }
1724
1800
  ]
1725
1801
  },
1726
1802
  {
1727
- "name": "get_tillage_terms",
1803
+ "name": "get_upland_rice_land_cover_terms",
1728
1804
  "query": {
1729
- "termType.keyword": "tillage",
1730
- "name": "tillage"
1805
+ "bool": {
1806
+ "must": [
1807
+ {
1808
+ "match": {
1809
+ "@type": "Term"
1810
+ }
1811
+ },
1812
+ {
1813
+ "match": {
1814
+ "termType.keyword": "landCover"
1815
+ }
1816
+ },
1817
+ {
1818
+ "match_phrase": {
1819
+ "name": "rice plant"
1820
+ }
1821
+ },
1822
+ {
1823
+ "match": {
1824
+ "name": "upland"
1825
+ }
1826
+ }
1827
+ ]
1828
+ }
1731
1829
  },
1732
1830
  "results": [
1733
1831
  {
1734
1832
  "@type": "Term",
1735
- "@id": "ridgeTillage"
1736
- },
1737
- {
1738
- "@type": "Term",
1739
- "@id": "noTillage"
1740
- },
1741
- {
1742
- "@type": "Term",
1743
- "@id": "fullTillage"
1744
- },
1745
- {
1746
- "@type": "Term",
1747
- "@id": "minimumTillage"
1748
- },
1749
- {
1750
- "@type": "Term",
1751
- "@id": "fullInversionTillage"
1752
- },
1753
- {
1754
- "@type": "Term",
1755
- "@id": "deepTillage"
1756
- },
1757
- {
1758
- "@type": "Term",
1759
- "@id": "mulchTillage"
1760
- },
1761
- {
1762
- "@type": "Term",
1763
- "@id": "stripTillage"
1833
+ "@id": "ricePlantUpland"
1764
1834
  }
1765
1835
  ]
1766
1836
  },
@@ -1777,11 +1847,11 @@
1777
1847
  },
1778
1848
  {
1779
1849
  "@type": "Term",
1780
- "@id": "ureaFormaldehydeKgN"
1850
+ "@id": "ureaAmmoniumSulphateKgN"
1781
1851
  },
1782
1852
  {
1783
1853
  "@type": "Term",
1784
- "@id": "sulphurCoatedUreaKgN"
1854
+ "@id": "ureaFormaldehydeKgN"
1785
1855
  },
1786
1856
  {
1787
1857
  "@type": "Term",
@@ -1789,11 +1859,11 @@
1789
1859
  },
1790
1860
  {
1791
1861
  "@type": "Term",
1792
- "@id": "ureaCalciumNitrateKgN"
1862
+ "@id": "sulphurCoatedUreaKgN"
1793
1863
  },
1794
1864
  {
1795
1865
  "@type": "Term",
1796
- "@id": "ureaAmmoniumSulphateKgN"
1866
+ "@id": "ureaCalciumNitrateKgN"
1797
1867
  }
1798
1868
  ]
1799
1869
  },
@@ -1833,11 +1903,11 @@
1833
1903
  "results": [
1834
1904
  {
1835
1905
  "@type": "Term",
1836
- "@id": "woodPellets"
1906
+ "@id": "woodFuel"
1837
1907
  },
1838
1908
  {
1839
1909
  "@type": "Term",
1840
- "@id": "woodFuel"
1910
+ "@id": "woodPellets"
1841
1911
  },
1842
1912
  {
1843
1913
  "@type": "Term",
@@ -79,7 +79,9 @@ def _copy_item_if_exists(source: dict, keys: List[str] = [], dest: dict = {}) ->
79
79
 
80
80
 
81
81
  def _get_landCover_term_id(product: dict) -> str:
82
- return get_lookup_value(product.get('term', {}), LAND_COVER_KEY, model=MODEL, model_key=LAND_COVER_KEY)
82
+ value = get_lookup_value(product.get('term', {}), LAND_COVER_KEY, model=MODEL, model_key=LAND_COVER_KEY)
83
+ # TODO: what should happen when there are multiple values?
84
+ return value.split(';')[0] if value else None
83
85
 
84
86
 
85
87
  def _get_items_with_relevant_term_type(cycles: List[dict], item_name: str, relevant_values: list):
@@ -111,6 +113,11 @@ def should_run(site: dict):
111
113
  )
112
114
  ]
113
115
 
116
+ products_crop_forage = _get_items_with_relevant_term_type(
117
+ cycles=cycles,
118
+ item_name="products",
119
+ relevant_values=[TermTermType.CROP, TermTermType.FORAGE]
120
+ )
114
121
  products_crop_forage = [
115
122
  _copy_item_if_exists(
116
123
  source=product,
@@ -120,11 +127,7 @@ def should_run(site: dict):
120
127
  "value": 100
121
128
  }
122
129
  )
123
- for product in _get_items_with_relevant_term_type(
124
- cycles=cycles,
125
- item_name="products",
126
- relevant_values=[TermTermType.CROP, TermTermType.FORAGE]
127
- )
130
+ for product in list(filter(_get_landCover_term_id, products_crop_forage))
128
131
  ]
129
132
 
130
133
  practices = [
@@ -150,9 +153,9 @@ def should_run(site: dict):
150
153
  model=MODEL,
151
154
  term=None,
152
155
  model_key=MODEL_KEY,
153
- products_crop_forage_id=log_blank_nodes_id(products_crop_forage),
154
- products_land_cover_id=log_blank_nodes_id(products_land_cover),
155
- practice_id=log_blank_nodes_id(practices)
156
+ products_crop_forage_ids=log_blank_nodes_id(products_crop_forage),
157
+ products_land_cover_ids=log_blank_nodes_id(products_land_cover),
158
+ practice_ids=log_blank_nodes_id(practices)
156
159
  )
157
160
 
158
161
  _should_run = any(products_crop_forage + products_land_cover + practices)