hestia-earth-models 0.61.8__py3-none-any.whl → 0.62.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.

Potentially problematic release.


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

@@ -995,33 +995,6 @@ def _validate_time_fraction_dict(
995
995
  ])
996
996
 
997
997
 
998
- def _build_update_dict(node: dict, years: list, target_year: int) -> dict:
999
- """
1000
- Build an update dictionary containing values and dates from a node that fall within a given year.
1001
-
1002
- This is only required if when `group_nodes_by_year` `mode = GroupNodesByYearMode.DATES`
1003
-
1004
- Parameters
1005
- ----------
1006
- node : dict
1007
- The node containing values and dates.
1008
- year : int
1009
- The year to be matched.
1010
-
1011
- Returns
1012
- -------
1013
- dict
1014
- An update dictionary containing "value" and "dates" keys.
1015
- """
1016
- valid_indices = {
1017
- i for i, y in enumerate(years) if y == target_year
1018
- }
1019
- return {
1020
- "value": [node.get("value")[i] for i in valid_indices],
1021
- "dates": [node.get("dates")[i] for i in valid_indices]
1022
- }
1023
-
1024
-
1025
998
  def group_nodes_by_year(
1026
999
  nodes: list[dict],
1027
1000
  default_node_duration: int = 1,
@@ -1057,7 +1030,7 @@ def group_nodes_by_year(
1057
1030
  should_run_node = GROUP_NODES_BY_YEAR_MODE_TO_SHOULD_RUN_NODE_FUNCTION[mode]
1058
1031
  get_node_datetime_range = GROUP_NODES_BY_YEAR_MODE_TO_GET_DATETIME_RANGE_FUNCTION[mode]
1059
1032
 
1060
- valid_nodes = [node for node in nodes if should_run_node(node)]
1033
+ valid_nodes = non_empty_list(flatten(split_node_by_dates(node) for node in nodes if should_run_node(node)))
1061
1034
 
1062
1035
  def group_node(groups: dict, index: int):
1063
1036
  node = valid_nodes[index]
@@ -1066,12 +1039,6 @@ def group_nodes_by_year(
1066
1039
  node, default_node_duration=default_node_duration
1067
1040
  )
1068
1041
 
1069
- # pre-parse the "dates" field so it doesn't get re-calculated in each iteration of the for-loop
1070
- years = (
1071
- [safe_parse_date(datestr).year for datestr in node.get("dates", [])]
1072
- if mode == GroupNodesByYearMode.DATES else []
1073
- )
1074
-
1075
1042
  range_start = node_datetime_range.start.year if node_datetime_range else 0
1076
1043
  range_end = node_datetime_range.end.year + 1 if node_datetime_range else 0
1077
1044
 
@@ -1085,7 +1052,6 @@ def group_nodes_by_year(
1085
1052
  is_final_year = _datetime_within_range(node_datetime_range.end, group_datetime_range)
1086
1053
 
1087
1054
  time_fraction_dict = _build_time_fraction_dict(group_datetime_range, node_datetime_range)
1088
- update_dict = _build_update_dict(node, years, year) if mode == GroupNodesByYearMode.DATES else {}
1089
1055
 
1090
1056
  should_run = (
1091
1057
  mode == GroupNodesByYearMode.DATES
@@ -1096,7 +1062,7 @@ def group_nodes_by_year(
1096
1062
  )
1097
1063
 
1098
1064
  should_run and groups[year].append(
1099
- node | time_fraction_dict | update_dict
1065
+ node | time_fraction_dict
1100
1066
  )
1101
1067
 
1102
1068
  return groups
@@ -1111,6 +1077,57 @@ def group_nodes_by_year(
1111
1077
  return dict(sorted(iterated.items())) if sort_result else iterated
1112
1078
 
1113
1079
 
1080
+ def split_node_by_dates(node: dict) -> list[dict]:
1081
+ """
1082
+ Split a node with an array-like `value` and `dates` with multiple elements into a list of nodes with a single
1083
+ `value` and `dates`. All other array-like node fields (`sd`, `min`, `max`, and `observations`) will be also be
1084
+ split. Any other fields will be copied with no modifications.
1085
+
1086
+ All split fields will still be array-like, but will only contain one element. Any array-like fields with a
1087
+ different number of elements to `value` will not be split.
1088
+
1089
+ This function should only run on nodes with array-like `value` and `dates` (e.g., nodes with `@type` == `Emission`,
1090
+ `Input`,`Measurement`, `Practice` or `Product`).
1091
+
1092
+ Parameters
1093
+ ----------
1094
+ node : dict
1095
+ A HESTIA blank node with array-like `value` and `dates` (and optional array-like fields `sd`, `min`, `max`, and
1096
+ `observations`).
1097
+
1098
+ Returns
1099
+ -------
1100
+ list[dict]
1101
+ A list of nodes with single `value` and `dates`.
1102
+ """
1103
+ REQUIRED_KEYS = ["value", "dates"]
1104
+ OPTIONAL_KEYS = ["sd", "min", "max", "observations"]
1105
+
1106
+ value = node.get("value", [])
1107
+ target_len = len(value) if isinstance(value, list) else -1
1108
+
1109
+ def should_run_key(key: str) -> bool:
1110
+ item = node.get(key, [])
1111
+ return isinstance(item, list) and len(item) == target_len
1112
+
1113
+ should_run = all([
1114
+ target_len > 0,
1115
+ all(should_run_key(key) for key in REQUIRED_KEYS)
1116
+ ])
1117
+
1118
+ valid_keys = REQUIRED_KEYS + [key for key in OPTIONAL_KEYS if should_run_key(key)]
1119
+
1120
+ def split(result: list[dict], index: int) -> list[dict]:
1121
+ update = {key: [node[key][index]] for key in valid_keys}
1122
+ result.append(node | update)
1123
+ return result
1124
+
1125
+ return (
1126
+ sorted(reduce(split, range(len(value)), list()), key=lambda node: node.get("dates", []))
1127
+ if should_run else [node]
1128
+ )
1129
+
1130
+
1114
1131
  def group_nodes_by_year_and_month(
1115
1132
  nodes: list[dict],
1116
1133
  default_node_duration: int = 1,
@@ -1 +1 @@
1
- VERSION = '0.61.8'
1
+ VERSION = '0.62.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hestia-earth-models
3
- Version: 0.61.8
3
+ Version: 0.62.0
4
4
  Summary: Hestia's set of modules for filling gaps in the activity data using external datasets (e.g. populating soil properties with a geospatial dataset using provided coordinates) and internal lookups (e.g. populating machinery use from fuel use). Includes rules for when gaps should be filled versus not (e.g. never gap fill yield, gap fill crop residue if yield provided etc.).
5
5
  Home-page: https://gitlab.com/hestia-earth/hestia-engine-models
6
6
  Author: Hestia Team
@@ -11,7 +11,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
11
  Classifier: Programming Language :: Python :: 3.6
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: hestia-earth.schema ==28.*
14
+ Requires-Dist: hestia-earth.schema ==29.*
15
15
  Requires-Dist: hestia-earth.utils >=0.13.0
16
16
  Requires-Dist: python-dateutil >=2.8.1
17
17
  Requires-Dist: CurrencyConverter ==0.16.8
@@ -4,7 +4,7 @@ hestia_earth/models/cache_sites.py,sha256=KQp9cUKE-aIcYJoMWEtKFYS8gBFfsx5LKQhqoW
4
4
  hestia_earth/models/log.py,sha256=b63I3qyTtQs17xxbq8RI0Fv2lvZ1oDZ9k0njhxqiFFk,3459
5
5
  hestia_earth/models/preload_requests.py,sha256=elhYQTxBVuFlZROWvZ3yErDzzMLdMUIjBhmpdaTUSi8,1012
6
6
  hestia_earth/models/requirements.py,sha256=znNZJAhwX2iYiKcAQXPftY7z_1MsNa0QxCXkXyHm_U0,17363
7
- hestia_earth/models/version.py,sha256=Gmx1Mzumxee0MDRwhnW69WRndkZUHweMwKOy4mZhmno,19
7
+ hestia_earth/models/version.py,sha256=20rNPRrr5iRqYOjgaG8FGBREz_Bc791OcD-8QH-p7UY,19
8
8
  hestia_earth/models/agribalyse2016/__init__.py,sha256=WvK0qCQbnYtg9oZxrACd1wGormZyXibPtpCnIQeDqbw,415
9
9
  hestia_earth/models/agribalyse2016/fuelElectricity.py,sha256=mrh8seYSYdTgcMDCETLiknuPeJehg071YoG4UiyW0yU,4404
10
10
  hestia_earth/models/agribalyse2016/machineryInfrastructureDepreciatedAmountPerCycle.py,sha256=_Rbngu0DzHKa62JwBl58ZC_ui1zLF2que_nB7ukhOQc,3392
@@ -69,7 +69,7 @@ hestia_earth/models/cycle/animal/input/properties.py,sha256=2bKyyclrt0O7zvtD1Ij7
69
69
  hestia_earth/models/cycle/completeness/__init__.py,sha256=rkwGtxIay_AleJCT7al_ngnix_xRqySVie7qvHXMQI0,1517
70
70
  hestia_earth/models/cycle/completeness/animalFeed.py,sha256=8Fo1TqwSuiPudvd2vJ-LVxSyOdD8mDCOZMvjuj5W2uo,1012
71
71
  hestia_earth/models/cycle/completeness/cropResidue.py,sha256=zSiu9h0NxEBDUWlaKBh1QcX4jDIklrs0BC2NWMCQQ80,2549
72
- hestia_earth/models/cycle/completeness/electricityFuel.py,sha256=fmBll9hQCUSVI5anQGHu3dcIauUseu4ZZQRYx6Cpu4w,1757
72
+ hestia_earth/models/cycle/completeness/electricityFuel.py,sha256=FWG8EuOPubTLDc3jMJv6NdFCgG0wOVgxv-5P9wA7Nys,2044
73
73
  hestia_earth/models/cycle/completeness/excreta.py,sha256=2yVxcuWjAh4hoEukaMJ90VZpkCL7SfpwIgzigbjVaF4,996
74
74
  hestia_earth/models/cycle/completeness/material.py,sha256=UQH2oRnUY-Q-_MVuOlTAYqQxc7wWDM5mi_iFmp9PlIQ,1362
75
75
  hestia_earth/models/cycle/completeness/seed.py,sha256=g4GOzRx249pEfr2beU9n5tzBiWA3hhxnqyiGri7QbEI,1662
@@ -94,7 +94,7 @@ hestia_earth/models/cycle/pre_checks/cache_sources.py,sha256=jCynHYIqOVizBSPKWKi
94
94
  hestia_earth/models/cycle/pre_checks/site.py,sha256=n26QBpRTvUIZ-_SyD8D2_0Ny_JsFG1977ZKUaZAIFb0,870
95
95
  hestia_earth/models/cycle/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
96
  hestia_earth/models/cycle/product/currency.py,sha256=lB1pCD1747Ke3oFoqjAKEHbIdHPfrHKNaJSni69iMUQ,2150
97
- hestia_earth/models/cycle/product/economicValueShare.py,sha256=bbEyasn6SoVRkQFfDq7tSfM0_xnfhen3MmjbDGLZN5o,7601
97
+ hestia_earth/models/cycle/product/economicValueShare.py,sha256=jSuwTa94OKnI4vn8B_DVkVyjRHSqDGoF6rAwl4NK1zk,8540
98
98
  hestia_earth/models/cycle/product/price.py,sha256=E5Q0TkfbbsJHZZD3cBGZvvHj0f2sJrgLGulRCyILTbY,1449
99
99
  hestia_earth/models/cycle/product/primary.py,sha256=FYyl-Mv8AmEml1nhDJwU01N4LrszJm6E31eztQDHzdg,1853
100
100
  hestia_earth/models/cycle/product/properties.py,sha256=PiwCod4dlMScTm_MQhY35QpeLRuHvdsc_nijv_7TqNM,1377
@@ -242,15 +242,15 @@ hestia_earth/models/ipcc2019/no3ToGroundwaterInorganicFertiliser.py,sha256=eyPfy
242
242
  hestia_earth/models/ipcc2019/no3ToGroundwaterOrganicFertiliser.py,sha256=px2SN-uaus2cftXzlsYCUAxLuon6BnDXmaFI9xhQrgU,3347
243
243
  hestia_earth/models/ipcc2019/noxToAirInorganicFertiliser.py,sha256=fmmFgjtvOD2TrrLY03jYly_KvDnCsAXqhL_tmZQQt-A,4480
244
244
  hestia_earth/models/ipcc2019/noxToAirOrganicFertiliser.py,sha256=9dx_MRTwJGxJRq6mj2EJQMdQ2w6j7lw0fQk0If_cIGc,4152
245
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py,sha256=3TPl6RvUlNHbc7TZiHWoqK-o2fCgAvlcLh2C__MNj8A,8728
245
+ hestia_earth/models/ipcc2019/organicCarbonPerHa.py,sha256=8rQifRZYQdoBz9HpoSbmrKiGP7ayQUZT78KEErgqtwc,8658
246
246
  hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py,sha256=YrjsBTmFbOw2DlGgcxf1B0d_NeNhE1Fl_OG4DrCPhLU,82293
247
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py,sha256=W3G0LbrfQp5lnYQj7CvznLtjH_7WVPk7-zBiujgD0yE,57867
247
+ hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py,sha256=xIp0Xu4Ke3lksR5fDyYT7f5qmjevV9oCtLvdNnvqvgA,57974
248
248
  hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py,sha256=CrQWsDhW--wNQ2HEc_zxdFKuIdBHEwOQnVJGA3HgPpQ,10856
249
- hestia_earth/models/ipcc2019/pastureGrass.py,sha256=Q3uX7IcTk0PmzxqEhU3JAcHb5LnUymZbmdRFP9xXsfo,8713
250
- hestia_earth/models/ipcc2019/pastureGrass_utils.py,sha256=nUJYYkovzF7QD4LeUqhV5mBYFKdrhxeG4gyPRv0Xpuk,16002
249
+ hestia_earth/models/ipcc2019/pastureGrass.py,sha256=FCp39CiMUwzvsAsX0-stLlDAjFy6g5brmr9-XD8TuN0,9318
250
+ hestia_earth/models/ipcc2019/pastureGrass_utils.py,sha256=J7Du1woOvEbqyAMX9cNQ2NYDYpiVAbYWMEn_w2oBVbM,15394
251
251
  hestia_earth/models/ipcc2019/utils.py,sha256=MSDMu15D9DnilFUgi4_6jYXC0FaKso3OODauGTMB6hs,6229
252
252
  hestia_earth/models/ipcc2019/animal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
253
- hestia_earth/models/ipcc2019/animal/pastureGrass.py,sha256=xPtuTiKeAvBhv9d7B6Upw_cbP6YxKykVJ3_p0S_EtZg,10689
253
+ hestia_earth/models/ipcc2019/animal/pastureGrass.py,sha256=hOPTRzwugjoPWhVMvi9JfWdROH0V2EE9n2jAksyFqL0,10936
254
254
  hestia_earth/models/ipcc2019/animal/weightAtMaturity.py,sha256=5smSAmKVCIlELCD6S_3I16YuSWNFhcClGDOdvrIuYsE,3657
255
255
  hestia_earth/models/ipcc2021/__init__.py,sha256=VTgGFKhwMmk_nuI1RRq0in27fHYVPBonlXlPK00K8no,409
256
256
  hestia_earth/models/ipcc2021/gwp100.py,sha256=v-DYU-11XnWI1Ns1GEiKrJqL3JafxvhTsLmuBuFcxJU,1021
@@ -364,7 +364,7 @@ hestia_earth/models/linkedImpactAssessment/landTransformationFromPermanentPastur
364
364
  hestia_earth/models/linkedImpactAssessment/utils.py,sha256=dGwGc2d-8_WQElTpfyPmz5vQtL-LHQRmiZnCTuPXMDs,1876
365
365
  hestia_earth/models/mocking/__init__.py,sha256=n3Fkkrvh8zHNWiJZmnfQ7WZ91JRzAO9P6pSG1JpwtXo,687
366
366
  hestia_earth/models/mocking/mock_search.py,sha256=dBCDRfbZmbMLKP21u_VYkxyimomqs-zztjX-_ZNKuuM,2036
367
- hestia_earth/models/mocking/search-results.json,sha256=b2D9kIA18EpfCUl36Fi0L4JL8EuTrm4-VzZoaYw9dOw,43543
367
+ hestia_earth/models/mocking/search-results.json,sha256=bXKQ-rzwrMA_DWaLa5FFHkRBmnmHaTwHZylVcEIULMw,43626
368
368
  hestia_earth/models/pooreNemecek2018/__init__.py,sha256=nPboL7ULJzL5nJD5q7q9VOZt_fxbKVm8fmn1Az5YkVY,417
369
369
  hestia_earth/models/pooreNemecek2018/aboveGroundCropResidueTotal.py,sha256=Qt-mel4dkhK6N5uUOutNOinCTFjbjtGzITaaI0LvYc4,2396
370
370
  hestia_earth/models/pooreNemecek2018/belowGroundCropResidue.py,sha256=JT0RybbvWVlo01FO8K0Yj41HrEaJT3Kj1xfayr2X-xw,2315
@@ -526,7 +526,7 @@ hestia_earth/models/utils/aggregated.py,sha256=sz6usleZmo_tC_hIvmGgYsX8-H0dulXmm
526
526
  hestia_earth/models/utils/animalProduct.py,sha256=M5IunAKGY6oZv3j1Ascl34ywyeLWApqOIlBzbtlA2FE,721
527
527
  hestia_earth/models/utils/aquacultureManagement.py,sha256=dxrbC1Xf140cohxTbSw6TxLAnAASWTdNZwBBam4yQnw,171
528
528
  hestia_earth/models/utils/array_builders.py,sha256=0_Ik0gKoh1QBijyb-55odh8_dIs-CWQ3lgUN1Hnc4Y8,18749
529
- hestia_earth/models/utils/blank_node.py,sha256=PTrjipqY35g0AjlFU_pn9AdZ6I26VBizW7Elr7sF-OY,41908
529
+ hestia_earth/models/utils/blank_node.py,sha256=y6Gyp6p-CWvMd5mgN-sZFtGy1Q22YLo-vYsL_bO7CaM,42672
530
530
  hestia_earth/models/utils/completeness.py,sha256=2-GusD9UycobDZq8y5jar0ZcOjyqnSbzPRT_5XMc4YA,1259
531
531
  hestia_earth/models/utils/constant.py,sha256=5H7odhRwU_LmUhYwf8c1LsdqXSYbLWkuknvtRDqUBTQ,3194
532
532
  hestia_earth/models/utils/crop.py,sha256=kG054fryqPSBpmzvJFBy_CLiOdjrt7RMk5uTItO5ADg,2246
@@ -651,7 +651,7 @@ tests/models/cycle/pre_checks/test_cache_sources.py,sha256=tvk7E1LlJSq2Sb2MKBRlx
651
651
  tests/models/cycle/pre_checks/test_site.py,sha256=2JTrsOXVGfNn7FlLiX7DPNs6AHdeZuVvjNZP6SCjEII,694
652
652
  tests/models/cycle/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
653
653
  tests/models/cycle/product/test_currency.py,sha256=r7TA0FDDS9U50-FolEMXESi4pvSmwXnQxAHrQh0lRjA,1222
654
- tests/models/cycle/product/test_economicValueShare.py,sha256=58EsOw5nZWGTsKK_LFblIz3YwmCXROT-GffHojmd674,4417
654
+ tests/models/cycle/product/test_economicValueShare.py,sha256=sFS-gKt6oglqeKuDqHsPfZ90cEROOIdydFsOu4E85eo,4624
655
655
  tests/models/cycle/product/test_price.py,sha256=zmWNdF2P4k2QTje_62NJDklCIwmk2vF8xuOoVzL9qf0,1193
656
656
  tests/models/cycle/product/test_primary.py,sha256=UfLOOxUkDyeSOmDv4NyN6v5Yf0RO9etZNT797fbCbpA,1862
657
657
  tests/models/cycle/product/test_properties.py,sha256=7pcBH_Ny8JeQ2dWXBU-ZSmY5iYl0f_qFejp8Vk5e1H8,1142
@@ -770,7 +770,7 @@ tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py,sha256=3Hv86L4X_Va2mZL
770
770
  tests/models/ipcc2019/test_ch4ToAirExcreta.py,sha256=e58NXmBW2SNVLUqQO9A66Xq6jiGTyhdFZDZk51JApF8,2902
771
771
  tests/models/ipcc2019/test_ch4ToAirFloodedRice.py,sha256=FAp5b45WdX5Ih4yGUOZ4CmVD8smW1Lw1tnulx9AKVBI,1980
772
772
  tests/models/ipcc2019/test_co2ToAirLimeHydrolysis.py,sha256=e5iuZ-kQNEVih0ZRgRPWqaUtXcLpfkoU7sQypbqA9_Y,1345
773
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py,sha256=cvgUMp3pIyPvyeCuL9-TIDJajIw4FoljN88JKc5GsMI,4166
773
+ tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py,sha256=KCZfRKdkVgZ8u_mFsE99-yZ-A53SKOzyG1edYtI26P0,4242
774
774
  tests/models/ipcc2019/test_co2ToAirUreaHydrolysis.py,sha256=MmtEME0xjsa3KojFk_fxOLK6RZM_6p5HIpY2DOFHVu4,1530
775
775
  tests/models/ipcc2019/test_croppingDuration.py,sha256=gLRXeR6Tqa7ciD9KTRfsIflSeIIWT2iOpZMdcxAQla4,1871
776
776
  tests/models/ipcc2019/test_ligninContent.py,sha256=eIKEN__ab-0R52EhlhPSBiHnmTl6xOf1XbI33O-W9A4,4146
@@ -791,13 +791,13 @@ tests/models/ipcc2019/test_no3ToGroundwaterInorganicFertiliser.py,sha256=e7REnQ9
791
791
  tests/models/ipcc2019/test_no3ToGroundwaterOrganicFertiliser.py,sha256=e1ZViD12qB3bLdH3TJw3GbBP8iqMen-UJbcFkytb3VQ,1609
792
792
  tests/models/ipcc2019/test_noxToAirInorganicFertiliser.py,sha256=NZBSBJLM_j2PEpHRON2ysgKNF8x5sHfQVoAKQdGsfzk,1537
793
793
  tests/models/ipcc2019/test_noxToAirOrganicFertiliser.py,sha256=LR5pjV5vRbgSSQAw8kYRp_ij4CHInzgaDS6EggQuBiw,1104
794
- tests/models/ipcc2019/test_organicCarbonPerHa.py,sha256=CtgRy-7qXBTF7ZnWV6l6hOV_d8b6um0T3grHXUOc9OM,13891
794
+ tests/models/ipcc2019/test_organicCarbonPerHa.py,sha256=q75Bq29hjmjPjbwFCNzTmTVOMr54izyXaeOlPPKQ5z8,13901
795
795
  tests/models/ipcc2019/test_organicCarbonPerHa_tier_1_utils.py,sha256=e5RpK4GlH9tNxbwEyPQkO2lMwYBtGNp8ha8j4bZF9eg,20699
796
796
  tests/models/ipcc2019/test_organicCarbonPerHa_tier_2_utils.py,sha256=gHAi0qr9vE2_TtyJOqOc5Wc8ZRIflQz8vKBOcvKTzCE,7020
797
797
  tests/models/ipcc2019/test_organicCarbonPerHa_utils.py,sha256=Zd2QlN_Q3k9djuByOH62A00tryVzlvNtsd46N79TTeU,1778
798
- tests/models/ipcc2019/test_pastureGrass.py,sha256=hn6tw-ifMTn00_WmYPIjRdm56SMF1w-eqETngVE29ns,3373
798
+ tests/models/ipcc2019/test_pastureGrass.py,sha256=xcFXpszkqgeJImWOp-JlJxpcSHQKC-Pi0zdaKfai4a4,2660
799
799
  tests/models/ipcc2019/animal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
800
- tests/models/ipcc2019/animal/test_pastureGrass.py,sha256=2ZbeIxxEZ9xaDkfCY2pLripmtOG89iHMTrPqa2-UuQg,1983
800
+ tests/models/ipcc2019/animal/test_pastureGrass.py,sha256=IifdYacwC_cXn5wHeLqq2e0fJeIe8WLWOumYKY36MrE,1979
801
801
  tests/models/ipcc2019/animal/test_weightAtMaturity.py,sha256=Tss9bTVz66yXVEBZT31KMm6gd45B9E1DJLqwYArPuYY,665
802
802
  tests/models/ipcc2021/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
803
803
  tests/models/ipcc2021/test_gwp100.py,sha256=JRklKMSg-OXopb9ZufGgl94deuMuJSsfNXRZDBtOZrE,1119
@@ -1061,7 +1061,7 @@ tests/models/usetoxV2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
1061
1061
  tests/models/usetoxV2/test_freshwaterEcotoxicityPotentialCtue.py,sha256=eq7Gcmfya9g0eOKKkuBhz8vq7xi_CmZ_LTSxueBwZt4,835
1062
1062
  tests/models/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1063
1063
  tests/models/utils/test_array_builders.py,sha256=1zTc5r6Y9fcQ3x67S9Am0G3ip4Kp9_MmiSqIvY-M6yc,6470
1064
- tests/models/utils/test_blank_node.py,sha256=hgom8mJPWqylnf4AfLgVlbYgAHAEcH8DngOdFidFMcw,34343
1064
+ tests/models/utils/test_blank_node.py,sha256=zOZvZ0OPrLQSKwkuYhf9KBOEUa-pMn1zK0jxqhI3HaE,38039
1065
1065
  tests/models/utils/test_crop.py,sha256=ve_BqT2XuLTWAH-8YOnVY4nzMUSXYYXPB8S-5RtGlf4,463
1066
1066
  tests/models/utils/test_cropResidueManagement.py,sha256=RQt8lexeJzCyxZceIutgDpw7BpcqmjsUB0C0yZC2QpY,930
1067
1067
  tests/models/utils/test_currency.py,sha256=BPsojPsY9QW2aj8vgbjkPQXU8GU6wDwwtPZ3HdC4KTU,277
@@ -1082,8 +1082,8 @@ tests/models/utils/test_source.py,sha256=mv3vHZV5cjpoLA2I1109-YUkuzAiuhbRSnv_76_
1082
1082
  tests/models/utils/test_term.py,sha256=M5Sa26v2gzQYbZ4H_fo7DspnaCx__-WtL-MULGapCWk,3509
1083
1083
  tests/models/webbEtAl2012AndSintermannEtAl2012/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1084
1084
  tests/models/webbEtAl2012AndSintermannEtAl2012/test_nh3ToAirOrganicFertiliser.py,sha256=qi2FNXS5Af2WDtm7nq_FsprH3BfCF0XxnE0XHmC4aIY,2244
1085
- hestia_earth_models-0.61.8.dist-info/LICENSE,sha256=AC7h7GAgCZGJK_Tzh6LUCrML9gQEfowWwecEw2w54QM,1154
1086
- hestia_earth_models-0.61.8.dist-info/METADATA,sha256=IWeDTAdOnEFZ1vddHFUvLfz428gHnUaA3OSm-n0-NG8,3350
1087
- hestia_earth_models-0.61.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
1088
- hestia_earth_models-0.61.8.dist-info/top_level.txt,sha256=1dqA9TqpOLTEgpqa-YBsmbCmmNU1y56AtfFGEceZ2A0,19
1089
- hestia_earth_models-0.61.8.dist-info/RECORD,,
1085
+ hestia_earth_models-0.62.0.dist-info/LICENSE,sha256=AC7h7GAgCZGJK_Tzh6LUCrML9gQEfowWwecEw2w54QM,1154
1086
+ hestia_earth_models-0.62.0.dist-info/METADATA,sha256=I4RMMfkN95mAgg48dBTcssIccEoKZqc1MLsXltrYgus,3350
1087
+ hestia_earth_models-0.62.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
1088
+ hestia_earth_models-0.62.0.dist-info/top_level.txt,sha256=1dqA9TqpOLTEgpqa-YBsmbCmmNU1y56AtfFGEceZ2A0,19
1089
+ hestia_earth_models-0.62.0.dist-info/RECORD,,
@@ -148,3 +148,11 @@ def test_run_complete_above_80_percent():
148
148
 
149
149
  value = run(cycle)
150
150
  assert value == expected
151
+
152
+
153
+ def test_run_complete_2_products():
154
+ with open(f"{fixtures_folder}/complete-2-products/cycle.jsonld", encoding='utf-8') as f:
155
+ cycle = json.load(f)
156
+
157
+ value = run(cycle)
158
+ assert value == []
@@ -5,9 +5,9 @@ from tests.utils import fixtures_path, fake_new_input
5
5
  from tests.models.ipcc2019.test_pastureGrass import MILK_YIELD_TERMS, WOOL_TERMS, TERMS_BY_ID
6
6
  from hestia_earth.models.ipcc2019.animal.pastureGrass import MODEL, MODEL_KEY, run
7
7
 
8
- class_path = f"hestia_earth.models.{MODEL}.{MODEL_KEY.replace('/', '.')}"
8
+ class_path = f"hestia_earth.models.{MODEL}.animal.{MODEL_KEY}"
9
9
  class_path_utils = f"hestia_earth.models.{MODEL}.pastureGrass_utils"
10
- fixtures_folder = f"{fixtures_path}/{MODEL}/{MODEL_KEY}"
10
+ fixtures_folder = f"{fixtures_path}/{MODEL}/animal/{MODEL_KEY}"
11
11
 
12
12
 
13
13
  def fake_download_hestia(term_id: str, *args): return TERMS_BY_ID[term_id]
@@ -22,6 +22,7 @@ RUN_SCENARIOS = [
22
22
  ("complex-overlapping-cycles", 5),
23
23
  ("missing-measurement-dates", 3),
24
24
  ("no-organic-carbon-measurements", 1), # Closes issue #700
25
+ ("non-consecutive-organic-carbon-measurements", 1), # Closes issue 827
25
26
  ("multiple-method-classifications", 5) # Closes issue #764
26
27
  ]
27
28
  """List of (subfolder: str, num_cycles: int)."""
@@ -84,7 +84,7 @@ DEFAULT_PROPERTIES = {
84
84
 
85
85
 
86
86
  def fake_calc_descriptive_stats(arr: NDArray, *_args, **_kwargs):
87
- return {"value": [row[0] for row in arr]}
87
+ return {"value": [round(row[0], 6) for row in arr]}
88
88
 
89
89
 
90
90
  def fake_find_term_property(term: dict, property: str, *_):
@@ -50,22 +50,6 @@ def test_run(*args):
50
50
  assert value == expected
51
51
 
52
52
 
53
- @patch(f"{class_path_utils}.download_hestia", side_effect=fake_download_hestia)
54
- @patch("hestia_earth.models.utils.property.download_hestia", side_effect=fake_download_hestia)
55
- @patch(f"{class_path}.get_wool_terms", return_value=WOOL_TERMS)
56
- @patch(f"hestia_earth.models.{MODEL}.utils.get_milkYield_terms", return_value=MILK_YIELD_TERMS)
57
- @patch(f"{class_path}._new_input", side_effect=fake_new_input)
58
- def test_run_with_feed(*args):
59
- with open(f"{fixtures_folder}/with-feed/cycle.jsonld", encoding='utf-8') as f:
60
- cycle = json.load(f)
61
-
62
- with open(f"{fixtures_folder}/with-feed/result.jsonld", encoding='utf-8') as f:
63
- expected = json.load(f)
64
-
65
- value = run(cycle)
66
- assert value == expected
67
-
68
-
69
53
  @patch(f"{class_path_utils}.download_hestia", side_effect=fake_download_hestia)
70
54
  @patch("hestia_earth.models.utils.property.download_hestia", side_effect=fake_download_hestia)
71
55
  @patch(f"{class_path}.get_wool_terms", return_value=WOOL_TERMS)
@@ -21,7 +21,8 @@ from hestia_earth.models.utils.blank_node import (
21
21
  get_node_value,
22
22
  group_nodes_by_year,
23
23
  group_nodes_by_year_and_month,
24
- GroupNodesByYearMode
24
+ GroupNodesByYearMode,
25
+ split_node_by_dates
25
26
  )
26
27
 
27
28
 
@@ -1017,33 +1018,67 @@ def test_group_nodes_by_year_multiple_values_and_dates(mock_parse, system_dateti
1017
1018
  "2001-02",
1018
1019
  "2002-03",
1019
1020
  "2003-01"
1021
+ ],
1022
+ "sd": [
1023
+ 0.8, 0.9, 1.0, 0.9, 0.8
1024
+ ],
1025
+ "observations": [
1026
+ 100, 100, 100, 100, 100
1020
1027
  ]
1021
1028
  }]
1022
1029
 
1023
1030
  EXPECTED = {
1024
- 2000: [{
1025
- "dates": ["2000-01", "2000-06"],
1026
- "fraction_of_node_duration": 0.32475598935226263,
1027
- "fraction_of_group_duration": 1.0,
1028
- "value": [1, 2]
1029
- }],
1031
+ 2000: [
1032
+ {
1033
+ "dates": ["2000-01"],
1034
+ "fraction_of_node_duration": 1.0,
1035
+ "fraction_of_group_duration": 0.08469945355191257,
1036
+ "value": [1],
1037
+ "sd": [0.8],
1038
+ "observations": [
1039
+ 100
1040
+ ]
1041
+ },
1042
+ {
1043
+ "dates": ["2000-06"],
1044
+ "fraction_of_node_duration": 1.0,
1045
+ "fraction_of_group_duration": 0.08196721311475409,
1046
+ "value": [2],
1047
+ "sd": [0.9],
1048
+ "observations": [
1049
+ 100
1050
+ ]
1051
+ }
1052
+ ],
1030
1053
  2001: [{
1031
1054
  "dates": ["2001-02"],
1032
- "fraction_of_node_duration": 0.323868677905945,
1033
- "fraction_of_group_duration": 1.0,
1034
- "value": [3]
1055
+ "fraction_of_node_duration": 1.0,
1056
+ "fraction_of_group_duration": 0.07671232876712329,
1057
+ "value": [3],
1058
+ "sd": [1.0],
1059
+ "observations": [
1060
+ 100
1061
+ ]
1035
1062
  }],
1036
1063
  2002: [{
1037
1064
  "dates": ["2002-03"],
1038
- "fraction_of_node_duration": 0.323868677905945,
1039
- "fraction_of_group_duration": 1.0,
1040
- "value": [4]
1065
+ "fraction_of_node_duration": 1.0,
1066
+ "fraction_of_group_duration": 0.08493150684931507,
1067
+ "value": [4],
1068
+ "sd": [0.9],
1069
+ "observations": [
1070
+ 100
1071
+ ]
1041
1072
  }],
1042
1073
  2003: [{
1043
1074
  "dates": ["2003-01"],
1044
- "fraction_of_node_duration": 0.027506654835847383,
1075
+ "fraction_of_node_duration": 1.0,
1045
1076
  "fraction_of_group_duration": 0.08493150684931507,
1046
- "value": [5]
1077
+ "value": [5],
1078
+ "sd": [0.8],
1079
+ "observations": [
1080
+ 100
1081
+ ]
1047
1082
  }]
1048
1083
  }
1049
1084
 
@@ -1134,3 +1169,107 @@ def test_group_nodes_by_year_and_month(mock_parse, system_datetime):
1134
1169
 
1135
1170
  result = group_nodes_by_year_and_month(MANAGEMENT)
1136
1171
  assert result == EXPECTED
1172
+
1173
+
1174
+ # node, expected
1175
+ PARAMS_SPLIT_NODE = [
1176
+ (
1177
+ {},
1178
+ [{}]
1179
+ ),
1180
+ (
1181
+ {"value": [1, 2, 3], "dates": ["2000"]},
1182
+ [{"value": [1, 2, 3], "dates": ["2000"]}]
1183
+ ),
1184
+ (
1185
+ {"value": [1, 2, 3], "startDate": "2000", "endDate": "2001"},
1186
+ [{"value": [1, 2, 3], "startDate": "2000", "endDate": "2001"}]
1187
+ ),
1188
+ (
1189
+ {"value": 1, "startDate": "2000", "endDate": "2001"},
1190
+ [{"value": 1, "startDate": "2000", "endDate": "2001"}]
1191
+ ),
1192
+ (
1193
+ {"value": None},
1194
+ [{"value": None}]
1195
+ ),
1196
+ (
1197
+ {"value": [1, 2, 3], "dates": ["2000", "2001", "2002"]},
1198
+ [
1199
+ {"value": [1], "dates": ["2000"]},
1200
+ {"value": [2], "dates": ["2001"]},
1201
+ {"value": [3], "dates": ["2002"]}
1202
+ ]
1203
+ ),
1204
+ (
1205
+ {
1206
+ "value": [1, 2],
1207
+ "dates": ["2000", "2001"],
1208
+ "sd": [0.816496, 0.816496],
1209
+ "min": [0, 1],
1210
+ "max": [2, 3],
1211
+ "observations": [3, 3]
1212
+ },
1213
+ [
1214
+ {
1215
+ "value": [1],
1216
+ "dates": ["2000"],
1217
+ "sd": [0.816496],
1218
+ "min": [0],
1219
+ "max": [2],
1220
+ "observations": [3]
1221
+ },
1222
+ {
1223
+ "value": [2],
1224
+ "dates": ["2001"],
1225
+ "sd": [0.816496],
1226
+ "min": [1],
1227
+ "max": [3],
1228
+ "observations": [3]
1229
+ }
1230
+ ]
1231
+ ),
1232
+ (
1233
+ {
1234
+ "value": [1, 2],
1235
+ "dates": ["2000", "2001"],
1236
+ "sd": [0.816496, 0.816496],
1237
+ "min": [0, 1],
1238
+ "max": [2, 3],
1239
+ "observations": [3]
1240
+ },
1241
+ [
1242
+ {
1243
+ "value": [1],
1244
+ "dates": ["2000"],
1245
+ "sd": [0.816496],
1246
+ "min": [0],
1247
+ "max": [2],
1248
+ "observations": [3]
1249
+ },
1250
+ {
1251
+ "value": [2],
1252
+ "dates": ["2001"],
1253
+ "sd": [0.816496],
1254
+ "min": [1],
1255
+ "max": [3],
1256
+ "observations": [3]
1257
+ }
1258
+ ]
1259
+ )
1260
+ ]
1261
+ IDS_SPLIT_NODE = [
1262
+ "no split -> empty node",
1263
+ "no split -> not enough dates", # len(value) and len(dates) MUST match
1264
+ "no split -> startDate & endDate",
1265
+ "no split -> non-iterable value", # i.e., on a Management or Animal node.
1266
+ "no split -> null value", # i.e., on a Animal node where value is not required.
1267
+ "value & dates",
1268
+ "descriptive statistics",
1269
+ "descriptive statistics w/ bad key" # if descriptive statistic keys have wrong length, don't split them
1270
+ ]
1271
+
1272
+
1273
+ @mark.parametrize("node, expected", PARAMS_SPLIT_NODE, ids=IDS_SPLIT_NODE)
1274
+ def test_split_node_by_dates(node, expected):
1275
+ assert split_node_by_dates(node) == expected