fmu-sumo 2.7.0__tar.gz → 2.8.1__tar.gz

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.
Files changed (67) hide show
  1. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.github/workflows/run_tests.yaml +1 -1
  2. {fmu_sumo-2.7.0/src/fmu_sumo.egg-info → fmu_sumo-2.8.1}/PKG-INFO +1 -1
  3. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/_version.py +3 -3
  4. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/_search_context.py +71 -1
  5. fmu_sumo-2.8.1/src/fmu/sumo/explorer/objects/ensembles.py +90 -0
  6. fmu_sumo-2.8.1/src/fmu/sumo/explorer/objects/realizations.py +96 -0
  7. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1/src/fmu_sumo.egg-info}/PKG-INFO +1 -1
  8. fmu_sumo-2.7.0/src/fmu/sumo/explorer/objects/ensembles.py +0 -31
  9. fmu_sumo-2.7.0/src/fmu/sumo/explorer/objects/realizations.py +0 -42
  10. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.github/pull_request_template.md +0 -0
  11. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.github/workflows/build_docs.yaml +0 -0
  12. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.github/workflows/check_formatting.yml +0 -0
  13. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.github/workflows/publish_release.yaml +0 -0
  14. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.gitignore +0 -0
  15. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.pre-commit-config.yaml +0 -0
  16. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/.readthedocs.yml +0 -0
  17. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/CONTRIBUTING.md +0 -0
  18. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/LICENSE +0 -0
  19. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/README.md +0 -0
  20. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/SECURITY.md +0 -0
  21. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/_static/equinor-logo.png +0 -0
  22. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/_static/equinor-logo2.jpg +0 -0
  23. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/_static/equinor_logo.jpg +0 -0
  24. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/_static/equinor_logo_only.jpg +0 -0
  25. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/_templates/layout.html +0 -0
  26. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/conf.py +0 -0
  27. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/explorer.rst +0 -0
  28. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/docs/index.rst +0 -0
  29. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/examples/explorer.ipynb +0 -0
  30. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/examples/explorer2.ipynb +0 -0
  31. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/examples/grids-and-properties.ipynb +0 -0
  32. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/examples/metrics.ipynb +0 -0
  33. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/examples/table-aggregation.ipynb +0 -0
  34. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/pyproject.toml +0 -0
  35. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/setup.cfg +0 -0
  36. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/__init__.py +0 -0
  37. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/__init__.py +0 -0
  38. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/__init__.py +0 -0
  39. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/cache.py +0 -0
  40. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/explorer.py +0 -0
  41. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/filters.py +0 -0
  42. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/__init__.py +0 -0
  43. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/_child.py +0 -0
  44. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/_document.py +0 -0
  45. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/_metrics.py +0 -0
  46. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/case.py +0 -0
  47. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/cases.py +0 -0
  48. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/cpgrid.py +0 -0
  49. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/cpgrid_property.py +0 -0
  50. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/cube.py +0 -0
  51. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/dictionary.py +0 -0
  52. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/ensemble.py +0 -0
  53. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/iteration.py +0 -0
  54. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/iterations.py +0 -0
  55. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/polygons.py +0 -0
  56. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/realization.py +0 -0
  57. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/surface.py +0 -0
  58. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/objects/table.py +0 -0
  59. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu/sumo/explorer/timefilter.py +0 -0
  60. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu_sumo.egg-info/SOURCES.txt +0 -0
  61. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu_sumo.egg-info/dependency_links.txt +0 -0
  62. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu_sumo.egg-info/requires.txt +0 -0
  63. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/src/fmu_sumo.egg-info/top_level.txt +0 -0
  64. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/tests/conftest.py +0 -0
  65. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/tests/context.py +0 -0
  66. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/tests/test_explorer.py +0 -0
  67. {fmu_sumo-2.7.0 → fmu_sumo-2.8.1}/tests/test_objects_table.py +0 -0
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  matrix:
14
14
  python-version: ["3.11", "3.12"]
15
- os: [ubuntu-latest, windows-latest, macos-13]
15
+ os: [ubuntu-latest, windows-latest, macos-15]
16
16
  exclude:
17
17
  - os: windows-latest
18
18
  python-version: "3.11"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu-sumo
3
- Version: 2.7.0
3
+ Version: 2.8.1
4
4
  Summary: Python package for interacting with Sumo in an FMU setting
5
5
  Author: Equinor
6
6
  License: Apache License
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2.7.0'
32
- __version_tuple__ = version_tuple = (2, 7, 0)
31
+ __version__ = version = '2.8.1'
32
+ __version_tuple__ = version_tuple = (2, 8, 1)
33
33
 
34
- __commit_id__ = commit_id = 'g748a3bb06'
34
+ __commit_id__ = commit_id = 'g085fb1035'
@@ -219,6 +219,30 @@ def _build_bucket_query_simple(query, field, size):
219
219
  }
220
220
 
221
221
 
222
+ def _build_composite_query(query, fields, size):
223
+ return {
224
+ "size": 0,
225
+ "query": query,
226
+ "aggs": {
227
+ "composite": {
228
+ "composite": {
229
+ "size": size,
230
+ "sources": [
231
+ {k: {"terms": {"field": v}}} for k, v in fields.items()
232
+ ],
233
+ }
234
+ }
235
+ },
236
+ }
237
+
238
+
239
+ def _extract_composite_results(res):
240
+ aggs = res["aggregations"]["composite"]
241
+ after_key = aggs.get("after_key")
242
+ buckets = [bucket["key"] for bucket in aggs["buckets"]]
243
+ return buckets, after_key
244
+
245
+
222
246
  def _set_after_key(query, field, after_key):
223
247
  if after_key is not None:
224
248
  query["aggs"][field]["composite"]["after"] = after_key
@@ -432,7 +456,7 @@ class SearchContext:
432
456
  else:
433
457
  return hits
434
458
  after = None
435
- with Pit(self._sumo, "1m") as pit:
459
+ async with Pit(self._sumo, "1m") as pit:
436
460
  while True:
437
461
  query = pit.stamp_query(_set_search_after(query, after))
438
462
  res = (
@@ -1027,6 +1051,52 @@ class SearchContext:
1027
1051
  }
1028
1052
  }
1029
1053
 
1054
+ def get_composite_agg(self, fields: Dict[str, str]):
1055
+ buckets_per_batch = 1000
1056
+ query = _build_composite_query(self._query, fields, buckets_per_batch)
1057
+ all_buckets = []
1058
+ after_key = None
1059
+ with Pit(self._sumo, "1m") as pit:
1060
+ while True:
1061
+ query = pit.stamp_query(
1062
+ _set_after_key(query, "composite", after_key)
1063
+ )
1064
+ res = self._sumo.post("/search", json=query)
1065
+ res = res.json()
1066
+ pit.update_from_result(res)
1067
+ buckets, after_key = _extract_composite_results(res)
1068
+ if len(buckets) == 0:
1069
+ break
1070
+ all_buckets = all_buckets + buckets
1071
+ if len(buckets) < buckets_per_batch:
1072
+ break
1073
+ pass
1074
+
1075
+ return all_buckets
1076
+
1077
+ async def get_composite_agg_async(self, fields: Dict[str, str]):
1078
+ buckets_per_batch = 1000
1079
+ query = _build_composite_query(self._query, fields, buckets_per_batch)
1080
+ all_buckets = []
1081
+ after_key = None
1082
+ async with Pit(self._sumo, "1m") as pit:
1083
+ while True:
1084
+ query = pit.stamp_query(
1085
+ _set_after_key(query, "composite", after_key)
1086
+ )
1087
+ res = await self._sumo.post_async("/search", json=query)
1088
+ res = res.json()
1089
+ pit.update_from_result(res)
1090
+ buckets, after_key = _extract_composite_results(res)
1091
+ if len(buckets) == 0:
1092
+ break
1093
+ all_buckets = all_buckets + buckets
1094
+ if len(buckets) < buckets_per_batch:
1095
+ break
1096
+ pass
1097
+
1098
+ return all_buckets
1099
+
1030
1100
  def _context_for_class(self, cls):
1031
1101
  return self.filter(cls=cls)
1032
1102
 
@@ -0,0 +1,90 @@
1
+ """Module for searchcontext for collection of ensembles."""
2
+
3
+ from copy import deepcopy
4
+ from typing import List
5
+
6
+ from fmu.sumo.explorer.objects.ensemble import Ensemble
7
+
8
+ from ._search_context import SearchContext
9
+
10
+
11
+ class Ensembles(SearchContext):
12
+ def __init__(self, sc, uuids):
13
+ super().__init__(sc._sumo, must=[{"ids": {"values": uuids}}])
14
+ self._hits = uuids
15
+ self._prototype = None
16
+ self._map = {}
17
+ return
18
+
19
+ def _maybe_prefetch(self, index):
20
+ return
21
+
22
+ async def _maybe_prefetch_async(self, index):
23
+ return
24
+
25
+ def filter(self, **kwargs):
26
+ sc = super().filter(**kwargs)
27
+ uuids = sc.get_field_values("fmu.ensemble.uuid.keyword")
28
+ return Ensembles(sc, uuids)
29
+
30
+ def get_object(self, uuid):
31
+ if self._prototype is None:
32
+ obj = super().get_object(uuid)
33
+ if len(self.get_field_values("fmu.case.uuid.keyword")) > 1:
34
+ return obj
35
+ # ELSE
36
+ self._prototype = obj.metadata
37
+ buckets = self.get_composite_agg(
38
+ {
39
+ "uuid": "fmu.ensemble.uuid.keyword",
40
+ "name": "fmu.ensemble.name.keyword",
41
+ }
42
+ )
43
+ self._map = {b["uuid"]: b for b in buckets}
44
+ pass
45
+ metadata = deepcopy(self._prototype)
46
+ b = self._map[uuid]
47
+ metadata["fmu"]["ensemble"] = b
48
+ return Ensemble(self._sumo, {"_id": uuid, "_source": metadata})
49
+
50
+ async def get_object_async(self, uuid):
51
+ if self._prototype is None:
52
+ obj = await super().get_object_async(uuid)
53
+ if (
54
+ len(await self.get_field_values_async("fmu.case.uuid.keyword"))
55
+ > 1
56
+ ):
57
+ return obj
58
+ # ELSE
59
+ self._prototype = obj.metadata
60
+ buckets = await self.get_composite_agg_async(
61
+ {
62
+ "uuid": "fmu.ensemble.uuid.keyword",
63
+ "name": "fmu.ensemble.name.keyword",
64
+ }
65
+ )
66
+ self._map = {b["uuid"]: b for b in buckets}
67
+ pass
68
+ metadata = deepcopy(self._prototype)
69
+ b = self._map[uuid]
70
+ metadata["fmu"]["ensemble"] = b
71
+ return Ensemble(self._sumo, {"_id": uuid, "_source": metadata})
72
+
73
+ @property
74
+ def classes(self) -> List[str]:
75
+ return ["ensemble"]
76
+
77
+ @property
78
+ async def classes_async(self) -> List[str]:
79
+ return ["ensemble"]
80
+
81
+ @property
82
+ def ensemblenames(self) -> List[str]:
83
+ return [self.get_object(uuid).ensemblename for uuid in self._hits]
84
+
85
+ @property
86
+ async def ensemblenames_async(self) -> List[str]:
87
+ return [
88
+ (await self.get_object_async(uuid)).ensemblename
89
+ for uuid in self._hits
90
+ ]
@@ -0,0 +1,96 @@
1
+ """Module for searchcontext for collection of realizations."""
2
+
3
+ from copy import deepcopy
4
+ from typing import List
5
+
6
+ from fmu.sumo.explorer.objects.realization import Realization
7
+
8
+ from ._search_context import SearchContext
9
+
10
+
11
+ class Realizations(SearchContext):
12
+ def __init__(self, sc, uuids):
13
+ super().__init__(sc._sumo, must=[{"ids": {"values": uuids}}])
14
+ self._hits = uuids
15
+ self._prototype = None
16
+ self._map = {}
17
+ return
18
+
19
+ def _maybe_prefetch(self, index):
20
+ return
21
+
22
+ async def _maybe_prefetch_async(self, index):
23
+ return
24
+
25
+ def filter(self, **kwargs):
26
+ sc = super().filter(**kwargs)
27
+ uuids = sc.get_field_values("fmu.realization.uuid.keyword")
28
+ return Realizations(self, uuids)
29
+
30
+ def get_object(self, uuid):
31
+ if self._prototype is None:
32
+ obj = super().get_object(uuid)
33
+ if len(self.get_field_values("fmu.realization.uuid.keyword")) == 1:
34
+ return obj
35
+ # ELSE
36
+ self._prototype = obj.metadata
37
+ buckets = self.get_composite_agg(
38
+ {
39
+ "uuid": "fmu.realization.uuid.keyword",
40
+ "name": "fmu.realization.name.keyword",
41
+ "id": "fmu.realization.id",
42
+ }
43
+ )
44
+ self._map = {b["uuid"]: b for b in buckets}
45
+ pass
46
+ metadata = deepcopy(self._prototype)
47
+ b = self._map[uuid]
48
+ metadata["fmu"]["realization"] = b
49
+ return Realization(self._sumo, {"_id": uuid, "_source": metadata})
50
+
51
+ async def get_object_async(self, uuid):
52
+ if self._prototype is None:
53
+ obj = await super().get_object_async(uuid)
54
+ if (
55
+ len(
56
+ await self.get_field_values_async(
57
+ "fmu.realization.uuid.keyword"
58
+ )
59
+ )
60
+ == 1
61
+ ):
62
+ return obj
63
+ # ELSE
64
+ self._prototype = obj.metadata
65
+ buckets = await self.get_composite_agg_async(
66
+ {
67
+ "uuid": "fmu.realization.uuid.keyword",
68
+ "name": "fmu.realization.name.keyword",
69
+ "id": "fmu.realization.id",
70
+ }
71
+ )
72
+ self._map = {b["uuid"]: b for b in buckets}
73
+ pass
74
+ metadata = deepcopy(self._prototype)
75
+ b = self._map[uuid]
76
+ metadata["fmu"]["realization"] = b
77
+ return Realization(self._sumo, {"_id": uuid, "_source": metadata})
78
+
79
+ @property
80
+ def classes(self) -> List[str]:
81
+ return ["realization"]
82
+
83
+ @property
84
+ async def classes_async(self) -> List[str]:
85
+ return ["realization"]
86
+
87
+ @property
88
+ def realizationids(self) -> List[int]:
89
+ return [self.get_object(uuid).realizationid for uuid in self._hits]
90
+
91
+ @property
92
+ async def realizationids_async(self) -> List[int]:
93
+ return [
94
+ (await self.get_object_async(uuid)).realizationid
95
+ for uuid in self._hits
96
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu-sumo
3
- Version: 2.7.0
3
+ Version: 2.8.1
4
4
  Summary: Python package for interacting with Sumo in an FMU setting
5
5
  Author: Equinor
6
6
  License: Apache License
@@ -1,31 +0,0 @@
1
- """Module for searchcontext for collection of ensembles."""
2
-
3
- from typing import List
4
-
5
- from ._search_context import SearchContext
6
-
7
-
8
- class Ensembles(SearchContext):
9
- def __init__(self, sc, uuids):
10
- super().__init__(sc._sumo, must=[{"ids": {"values": uuids}}])
11
- self._hits = uuids
12
- return
13
-
14
- @property
15
- def classes(self) -> List[str]:
16
- return ["ensemble"]
17
-
18
- @property
19
- async def classes_async(self) -> List[str]:
20
- return ["ensemble"]
21
-
22
- def _maybe_prefetch(self, index):
23
- return
24
-
25
- async def _maybe_prefetch_async(self, index):
26
- return
27
-
28
- def filter(self, **kwargs):
29
- sc = super().filter(**kwargs)
30
- uuids = sc.get_field_values("fmu.ensemble.uuid.keyword")
31
- return Ensembles(sc, uuids)
@@ -1,42 +0,0 @@
1
- """Module for searchcontext for collection of realizations."""
2
-
3
- from typing import List
4
-
5
- from ._search_context import SearchContext
6
-
7
-
8
- class Realizations(SearchContext):
9
- def __init__(self, sc, uuids):
10
- super().__init__(sc._sumo, must=[{"ids": {"values": uuids}}])
11
- self._hits = uuids
12
- return
13
-
14
- def _maybe_prefetch(self, index):
15
- return
16
-
17
- async def _maybe_prefetch_async(self, index):
18
- return
19
-
20
- def filter(self, **kwargs):
21
- sc = super().filter(**kwargs)
22
- uuids = sc.get_field_values("fmu.realization.uuid.keyword")
23
- return Realizations(self, uuids)
24
-
25
- @property
26
- def classes(self) -> List[str]:
27
- return ["realization"]
28
-
29
- @property
30
- async def classes_async(self) -> List[str]:
31
- return ["realization"]
32
-
33
- @property
34
- def realizationids(self) -> List[int]:
35
- return [self.get_object(uuid).realizationid for uuid in self._hits]
36
-
37
- @property
38
- async def realizationids_async(self) -> List[int]:
39
- return [
40
- (await self.get_object_async(uuid)).realizationid
41
- for uuid in self._hits
42
- ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes