polytope-python 1.0.35__tar.gz → 1.0.37__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 (120) hide show
  1. {polytope_python-1.0.35/polytope_python.egg-info → polytope_python-1.0.37}/PKG-INFO +1 -1
  2. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/backends/fdb.py +16 -8
  3. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/engine/hullslicer.py +16 -5
  4. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/polytope.py +7 -0
  5. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/shapes.py +49 -8
  6. polytope_python-1.0.37/polytope_feature/version.py +1 -0
  7. {polytope_python-1.0.35 → polytope_python-1.0.37/polytope_python.egg-info}/PKG-INFO +1 -1
  8. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_python.egg-info/SOURCES.txt +1 -0
  9. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_point_shape.py +9 -3
  10. polytope_python-1.0.37/tests/test_point_union.py +199 -0
  11. polytope_python-1.0.35/polytope_feature/version.py +0 -1
  12. {polytope_python-1.0.35 → polytope_python-1.0.37}/LICENSE +0 -0
  13. {polytope_python-1.0.35 → polytope_python-1.0.37}/MANIFEST.in +0 -0
  14. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/__init__.py +0 -0
  15. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/__init__.py +0 -0
  16. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/backends/__init__.py +0 -0
  17. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/backends/datacube.py +0 -0
  18. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/backends/mock.py +0 -0
  19. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/backends/xarray.py +0 -0
  20. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/datacube_axis.py +0 -0
  21. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/index_tree_pb2.py +0 -0
  22. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/tensor_index_tree.py +0 -0
  23. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/__init__.py +0 -0
  24. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_cyclic/__init__.py +0 -0
  25. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
  26. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/__init__.py +0 -0
  27. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py +0 -0
  28. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -0
  29. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py +0 -0
  30. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +0 -0
  31. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +0 -0
  32. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +0 -0
  33. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_gaussian.py +0 -0
  34. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +0 -0
  35. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py +0 -0
  36. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_merger/__init__.py +0 -0
  37. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py +0 -0
  38. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_reverse/__init__.py +0 -0
  39. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
  40. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_transformations.py +0 -0
  41. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_type_change/__init__.py +0 -0
  42. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py +0 -0
  43. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/datacube/tree_encoding.py +0 -0
  44. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/engine/__init__.py +0 -0
  45. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/engine/engine.py +0 -0
  46. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/options.py +0 -0
  47. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/__init__.py +0 -0
  48. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/combinatorics.py +0 -0
  49. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/exceptions.py +0 -0
  50. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/geometry.py +0 -0
  51. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/list_tools.py +0 -0
  52. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_feature/utility/profiling.py +0 -0
  53. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_python.egg-info/dependency_links.txt +0 -0
  54. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_python.egg-info/not-zip-safe +0 -0
  55. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_python.egg-info/requires.txt +0 -0
  56. {polytope_python-1.0.35 → polytope_python-1.0.37}/polytope_python.egg-info/top_level.txt +0 -0
  57. {polytope_python-1.0.35 → polytope_python-1.0.37}/pyproject.toml +0 -0
  58. {polytope_python-1.0.35 → polytope_python-1.0.37}/requirements.txt +0 -0
  59. {polytope_python-1.0.35 → polytope_python-1.0.37}/setup.cfg +0 -0
  60. {polytope_python-1.0.35 → polytope_python-1.0.37}/setup.py +0 -0
  61. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_axis_mappers.py +0 -0
  62. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_bad_request_error.py +0 -0
  63. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_combinatorics.py +0 -0
  64. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_axis_over_negative_vals.py +0 -0
  65. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_axis_slicer_not_0.py +0 -0
  66. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_axis_slicing.py +0 -0
  67. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_nearest.py +0 -0
  68. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_simple.py +0 -0
  69. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_cyclic_snapping.py +0 -0
  70. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_datacube_axes_init.py +0 -0
  71. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_datacube_mock.py +0 -0
  72. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_datacube_xarray.py +0 -0
  73. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_date_time_unmerged.py +0 -0
  74. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_ecmwf_oper_data_fdb.py +0 -0
  75. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_engine_slicer.py +0 -0
  76. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_fdb_datacube.py +0 -0
  77. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_fdb_unmap_tree.py +0 -0
  78. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_float_type.py +0 -0
  79. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_healpix_mapper.py +0 -0
  80. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_healpix_nested_grid.py +0 -0
  81. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_hull_slicer.py +0 -0
  82. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_hullslicer_engine.py +0 -0
  83. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_incomplete_tree_fdb.py +0 -0
  84. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_local_grid_cyclic.py +0 -0
  85. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_local_regular_grid.py +0 -0
  86. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_local_swiss_grid.py +0 -0
  87. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_mappers.py +0 -0
  88. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_merge_cyclic_octahedral.py +0 -0
  89. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_merge_octahedral_one_axis.py +0 -0
  90. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_merge_transformation.py +0 -0
  91. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_multiple_param_fdb.py +0 -0
  92. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_octahedral_grid.py +0 -0
  93. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_override_md5_hash_options.py +0 -0
  94. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_point_nearest.py +0 -0
  95. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_profiling_requesttree.py +0 -0
  96. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_reduced_ll_grid.py +0 -0
  97. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_regular_grid.py +0 -0
  98. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_regular_reduced_grid.py +0 -0
  99. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_request_tree.py +0 -0
  100. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_request_trees_after_slicing.py +0 -0
  101. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_reverse_transformation.py +0 -0
  102. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_shapes.py +0 -0
  103. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slice_date_range_fdb.py +0 -0
  104. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slice_date_range_fdb_v2.py +0 -0
  105. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slice_fdb_box.py +0 -0
  106. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicer_engine.py +0 -0
  107. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicer_era5.py +0 -0
  108. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicer_xarray.py +0 -0
  109. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicing_unsliceable_axis.py +0 -0
  110. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicing_xarray_3D.py +0 -0
  111. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_slicing_xarray_4D.py +0 -0
  112. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_snapping.py +0 -0
  113. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_snapping_real_data.py +0 -0
  114. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_tree_protobuf.py +0 -0
  115. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_tree_protobuf_encoding.py +0 -0
  116. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_tree_protobuf_encoding_fdb.py +0 -0
  117. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_type_change_transformation.py +0 -0
  118. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_union_gj.py +0 -0
  119. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_union_point_box.py +0 -0
  120. {polytope_python-1.0.35 → polytope_python-1.0.37}/tests/test_wave_spectra_data.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polytope-python
3
- Version: 1.0.35
3
+ Version: 1.0.37
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -227,17 +227,25 @@ class FDBDatacube(Datacube):
227
227
  first_ax_name = requests.children[0].axis.name
228
228
  second_ax_name = requests.children[0].children[0].axis.name
229
229
 
230
- if first_ax_name not in self.nearest_search.keys() or second_ax_name not in self.nearest_search.keys():
230
+ axes_in_nearest_search = [
231
+ first_ax_name not in self.nearest_search.keys(),
232
+ second_ax_name not in self.nearest_search.keys(),
233
+ ]
234
+
235
+ if all(not item for item in axes_in_nearest_search):
231
236
  raise Exception("nearest point search axes are wrong")
232
237
 
233
238
  second_ax = requests.children[0].children[0].axis
234
239
 
235
- nearest_pts = [
236
- [lat_val, second_ax._remap_val_to_axis_range(lon_val)]
237
- for (lat_val, lon_val) in zip(
238
- self.nearest_search[first_ax_name][0], self.nearest_search[second_ax_name][0]
239
- )
240
- ]
240
+ nearest_pts = self.nearest_search.get((first_ax_name, second_ax_name), None)
241
+ if nearest_pts is None:
242
+ nearest_pts = self.nearest_search.get((second_ax_name, first_ax_name), None)
243
+ for i, pt in enumerate(nearest_pts):
244
+ nearest_pts[i] = [pt[1], pt[0]]
245
+
246
+ transformed_nearest_pts = []
247
+ for point in nearest_pts:
248
+ transformed_nearest_pts.append([point[0], second_ax._remap_val_to_axis_range(point[1])])
241
249
 
242
250
  found_latlon_pts = []
243
251
  for lat_child in requests.children:
@@ -246,7 +254,7 @@ class FDBDatacube(Datacube):
246
254
 
247
255
  # now find the nearest lat lon to the points requested
248
256
  nearest_latlons = []
249
- for pt in nearest_pts:
257
+ for pt in transformed_nearest_pts:
250
258
  nearest_latlon = nearest_pt(found_latlon_pts, pt)
251
259
  nearest_latlons.append(nearest_latlon)
252
260
 
@@ -8,7 +8,7 @@ import scipy.spatial
8
8
  from ..datacube.backends.datacube import Datacube
9
9
  from ..datacube.datacube_axis import UnsliceableDatacubeAxis
10
10
  from ..datacube.tensor_index_tree import TensorIndexTree
11
- from ..shapes import ConvexPolytope
11
+ from ..shapes import ConvexPolytope, Product
12
12
  from ..utility.combinatorics import group, tensor_product
13
13
  from ..utility.exceptions import UnsliceableShapeError
14
14
  from ..utility.geometry import lerp
@@ -76,8 +76,6 @@ class HullSlicer(Engine):
76
76
  upper = ax.from_float(upper + tol)
77
77
  flattened = node.flatten()
78
78
  method = polytope.method
79
- if method == "nearest":
80
- datacube.nearest_search[ax.name] = polytope.points
81
79
 
82
80
  # NOTE: caching
83
81
  # Create a coupled_axes list inside of datacube and add to it during axis formation, then here
@@ -214,7 +212,11 @@ class HullSlicer(Engine):
214
212
 
215
213
  # Convert the polytope points to float type to support triangulation and interpolation
216
214
  for p in polytopes:
217
- self._unique_continuous_points(p, datacube)
215
+ if isinstance(p, Product):
216
+ for poly in p.polytope():
217
+ self._unique_continuous_points(poly, datacube)
218
+ else:
219
+ self._unique_continuous_points(p, datacube)
218
220
 
219
221
  groups, input_axes = group(polytopes)
220
222
  datacube.validate(input_axes)
@@ -233,7 +235,16 @@ class HullSlicer(Engine):
233
235
  new_c.extend(combi)
234
236
  else:
235
237
  new_c.append(combi)
236
- r["unsliced_polytopes"] = set(new_c)
238
+ # NOTE TODO: here some of the polys in new_c can be a Product shape instead of a ConvexPolytope
239
+ # -> need to go through the polytopes in new_c and replace the Products with their sub-ConvexPolytopes
240
+ final_polys = []
241
+ for poly in new_c:
242
+ if isinstance(poly, Product):
243
+ final_polys.extend(poly.polytope())
244
+ else:
245
+ final_polys.append(poly)
246
+ # r["unsliced_polytopes"] = set(new_c)
247
+ r["unsliced_polytopes"] = set(final_polys)
237
248
  current_nodes = [r]
238
249
  for ax in datacube.axes.values():
239
250
  next_nodes = []
@@ -64,6 +64,13 @@ class Polytope:
64
64
  """Higher-level API which takes a request and uses it to slice the datacube"""
65
65
  logging.info("Starting request for %s ", self.context)
66
66
  self.datacube.check_branching_axes(request)
67
+ for polytope in request.polytopes():
68
+ method = polytope.method
69
+ if method == "nearest":
70
+ if self.datacube.nearest_search.get(tuple(polytope.axes()), None) is None:
71
+ self.datacube.nearest_search[tuple(polytope.axes())] = polytope.values
72
+ else:
73
+ self.datacube.nearest_search[tuple(polytope.axes())].append(polytope.values[0])
67
74
  request_tree = self.engine.extract(self.datacube, request.polytopes())
68
75
  logging.info("Created request tree for %s ", self.context)
69
76
  self.datacube.get(request_tree, self.context)
@@ -61,6 +61,44 @@ class ConvexPolytope(Shape):
61
61
  return [self]
62
62
 
63
63
 
64
+ class Product(Shape):
65
+ """Shape that takes two polytopes and 'multiplies' them together to obtain higher-dimensional shape"""
66
+
67
+ def __init__(self, *polytopes, method, value):
68
+ # TODO
69
+ all_axes = []
70
+ for poly in polytopes:
71
+ for ax in poly.axes():
72
+ if ax not in all_axes:
73
+ all_axes.append(ax)
74
+ self._axes = all_axes
75
+ # Check there weren't any duplicates in the polytopes' axes
76
+ assert len(self._axes) == len(all_axes)
77
+
78
+ self._polytopes = []
79
+ for poly in polytopes:
80
+ self._polytopes.extend(poly.polytope())
81
+
82
+ self.is_in_union = False
83
+ self.method = method
84
+ self.values = value
85
+
86
+ self.is_orthogonal = False
87
+
88
+ polys_orthogonal = [poly.is_orthogonal for poly in polytopes]
89
+ if all(polys_orthogonal):
90
+ self.is_orthogonal = True
91
+
92
+ def add_to_union(self):
93
+ self.is_in_union = True
94
+
95
+ def axes(self):
96
+ return self._axes
97
+
98
+ def polytope(self):
99
+ return self._polytopes
100
+
101
+
64
102
  # This is the only shape which can slice on axes without a discretizer or interpolator
65
103
  class Select(Shape):
66
104
  """Matches several discrete values"""
@@ -89,19 +127,22 @@ class Point(Shape):
89
127
  self._axes = axes
90
128
  self.values = values
91
129
  self.method = method
92
- self.polytopes = []
93
- if method == "nearest":
94
- assert len(self.values) == 1
95
- for i in range(len(axes)):
96
- polytope_points = [v[i] for v in self.values]
97
- self.polytopes.extend(
98
- [ConvexPolytope([axes[i]], [[point]], self.method, is_orthogonal=True) for point in polytope_points]
99
- )
130
+ assert len(values) == 1
100
131
 
101
132
  def axes(self):
102
133
  return self._axes
103
134
 
104
135
  def polytope(self):
136
+ # TODO: change this to use the Product instead and return a Product here of the two 1D selects
137
+
138
+ polytopes = []
139
+ for point in self.values:
140
+ poly_to_mult = []
141
+ for i in range(len(self._axes)):
142
+ poly_to_mult.append(ConvexPolytope([self._axes[i]], [[point[i]]], self.method, is_orthogonal=True))
143
+ polytopes.append(Product(*poly_to_mult, method=self.method, value=[point]))
144
+ self.polytopes = polytopes
145
+
105
146
  return self.polytopes
106
147
 
107
148
  def __repr__(self):
@@ -0,0 +1 @@
1
+ __version__ = "1.0.37"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polytope-python
3
- Version: 1.0.35
3
+ Version: 1.0.37
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -88,6 +88,7 @@ tests/test_octahedral_grid.py
88
88
  tests/test_override_md5_hash_options.py
89
89
  tests/test_point_nearest.py
90
90
  tests/test_point_shape.py
91
+ tests/test_point_union.py
91
92
  tests/test_profiling_requesttree.py
92
93
  tests/test_reduced_ll_grid.py
93
94
  tests/test_regular_grid.py
@@ -4,7 +4,7 @@ import xarray as xr
4
4
 
5
5
  from polytope_feature.engine.hullslicer import HullSlicer
6
6
  from polytope_feature.polytope import Polytope, Request
7
- from polytope_feature.shapes import Point, Select
7
+ from polytope_feature.shapes import Point, Select, Union
8
8
 
9
9
 
10
10
  class TestSlicing3DXarrayDatacube:
@@ -30,20 +30,26 @@ class TestSlicing3DXarrayDatacube:
30
30
  assert result.leaves[0].axis.name == "level"
31
31
 
32
32
  def test_multiple_points(self):
33
- request = Request(Point(["step", "level"], [[3, 10], [3, 12]]), Select("date", ["2000-01-01"]))
33
+ # request = Request(Point(["step", "level"], [[3, 10], [3, 12]]), Select("date", ["2000-01-01"]))
34
+ request = Request(
35
+ Union(["step", "level"], Point(["step", "level"], [[3, 10]]), Point(["step", "level"], [[3, 12]])),
36
+ Select("date", ["2000-01-01"]),
37
+ )
34
38
  result = self.API.retrieve(request)
35
39
  result.pprint()
36
- assert len(result.leaves) == 1
40
+ assert len(result.leaves) == 2
37
41
  assert result.leaves[0].axis.name == "level"
38
42
 
39
43
  def test_point_surrounding_step(self):
40
44
  request = Request(Point(["step", "level"], [[2, 10]], method="surrounding"), Select("date", ["2000-01-01"]))
41
45
  result = self.API.retrieve(request)
46
+ result.pprint()
42
47
  assert len(result.leaves) == 1
43
48
  assert np.shape(result.leaves[0].result[1]) == (1, 2, 3)
44
49
 
45
50
  def test_point_surrounding_exact_step(self):
46
51
  request = Request(Point(["step", "level"], [[3, 10]], method="surrounding"), Select("date", ["2000-01-01"]))
47
52
  result = self.API.retrieve(request)
53
+ result.pprint()
48
54
  assert len(result.leaves) == 1
49
55
  assert np.shape(result.leaves[0].result[1]) == (1, 3, 3)
@@ -0,0 +1,199 @@
1
+ import pandas as pd
2
+ import pytest
3
+
4
+ from polytope_feature.engine.hullslicer import HullSlicer
5
+ from polytope_feature.polytope import Polytope, Request
6
+ from polytope_feature.shapes import Point, Select, Span, Union
7
+
8
+
9
+ class TestSlicingFDBDatacube:
10
+ def setup_method(self, method):
11
+ # Create a dataarray with 3 labelled axes using different index types
12
+ self.options = {
13
+ "axis_config": [
14
+ {"axis_name": "number", "transformations": [{"name": "type_change", "type": "int"}]},
15
+ {"axis_name": "step", "transformations": [{"name": "type_change", "type": "int"}]},
16
+ {
17
+ "axis_name": "date",
18
+ "transformations": [{"name": "merge", "other_axis": "time", "linkers": ["T", "00"]}],
19
+ },
20
+ {
21
+ "axis_name": "values",
22
+ "transformations": [
23
+ {"name": "mapper", "type": "octahedral", "resolution": 1280, "axes": ["latitude", "longitude"]}
24
+ ],
25
+ },
26
+ {"axis_name": "latitude", "transformations": [{"name": "reverse", "is_reverse": True}]},
27
+ {"axis_name": "longitude", "transformations": [{"name": "cyclic", "range": [0, 360]}]},
28
+ ],
29
+ "pre_path": {"class": "od", "expver": "0001", "levtype": "sfc", "stream": "oper"},
30
+ "compressed_axes_config": [
31
+ "longitude",
32
+ "latitude",
33
+ "levtype",
34
+ "step",
35
+ "date",
36
+ "domain",
37
+ "expver",
38
+ "param",
39
+ "class",
40
+ "stream",
41
+ "type",
42
+ ],
43
+ }
44
+
45
+ # Testing different shapes
46
+ @pytest.mark.fdb
47
+ def test_fdb_datacube(self):
48
+ import pygribjump as gj
49
+
50
+ request = Request(
51
+ Select("step", [0]),
52
+ Select("levtype", ["sfc"]),
53
+ Span("date", pd.Timestamp("20230625T120000"), pd.Timestamp("20230626T120000")),
54
+ Select("domain", ["g"]),
55
+ Select("expver", ["0001"]),
56
+ Select("param", ["167"]),
57
+ Select("class", ["od"]),
58
+ Select("stream", ["oper"]),
59
+ Select("type", ["an"]),
60
+ Union(
61
+ ["latitude", "longitude"],
62
+ Point(["latitude", "longitude"], [[20, 20]], method="nearest"),
63
+ Point(["latitude", "longitude"], [[0, 0]], method="nearest"),
64
+ Point(["latitude", "longitude"], [[0, 20]], method="nearest"),
65
+ Point(["latitude", "longitude"], [[25, 30]], method="nearest"),
66
+ Point(["latitude", "longitude"], [[-30, 90]], method="nearest"),
67
+ Point(["latitude", "longitude"], [[-60, -30]], method="nearest"),
68
+ Point(["latitude", "longitude"], [[-15, -45]], method="nearest"),
69
+ Point(["latitude", "longitude"], [[20, 0]], method="nearest"),
70
+ ),
71
+ )
72
+
73
+ self.fdbdatacube = gj.GribJump()
74
+ self.slicer = HullSlicer()
75
+ self.API = Polytope(
76
+ datacube=self.fdbdatacube,
77
+ engine=self.slicer,
78
+ options=self.options,
79
+ )
80
+ result = self.API.retrieve(request)
81
+ result.pprint()
82
+ assert len(result.leaves) == 8
83
+
84
+ @pytest.mark.fdb
85
+ def test_fdb_datacube_surrounding(self):
86
+ import pygribjump as gj
87
+
88
+ request = Request(
89
+ Select("step", [0]),
90
+ Select("levtype", ["sfc"]),
91
+ Span("date", pd.Timestamp("20230625T120000"), pd.Timestamp("20230626T120000")),
92
+ Select("domain", ["g"]),
93
+ Select("expver", ["0001"]),
94
+ Select("param", ["167"]),
95
+ Select("class", ["od"]),
96
+ Select("stream", ["oper"]),
97
+ Select("type", ["an"]),
98
+ Union(
99
+ ["latitude", "longitude"],
100
+ Point(["latitude", "longitude"], [[25, 30]], method="surrounding"),
101
+ Point(["latitude", "longitude"], [[-15, -45]], method="surrounding"),
102
+ ),
103
+ )
104
+
105
+ self.fdbdatacube = gj.GribJump()
106
+ self.slicer = HullSlicer()
107
+ self.API = Polytope(
108
+ datacube=self.fdbdatacube,
109
+ engine=self.slicer,
110
+ options=self.options,
111
+ )
112
+ result = self.API.retrieve(request)
113
+ result.pprint()
114
+ assert len(result.leaves) == 4
115
+ tot_leaves = 0
116
+ for leaf in result.leaves:
117
+ tot_leaves += len(leaf.result)
118
+ assert tot_leaves == 9
119
+
120
+ @pytest.mark.fdb
121
+ def test_fdb_datacube_axis_order(self):
122
+ import pygribjump as gj
123
+
124
+ request = Request(
125
+ Select("step", [0]),
126
+ Select("levtype", ["sfc"]),
127
+ Span("date", pd.Timestamp("20230625T120000"), pd.Timestamp("20230626T120000")),
128
+ Select("domain", ["g"]),
129
+ Select("expver", ["0001"]),
130
+ Select("param", ["167"]),
131
+ Select("class", ["od"]),
132
+ Select("stream", ["oper"]),
133
+ Select("type", ["an"]),
134
+ Union(
135
+ ["latitude", "longitude"],
136
+ Point(["latitude", "longitude"], [[25, 30]], method="nearest"),
137
+ ),
138
+ )
139
+
140
+ inverted_request = Request(
141
+ Select("step", [0]),
142
+ Select("levtype", ["sfc"]),
143
+ Span("date", pd.Timestamp("20230625T120000"), pd.Timestamp("20230626T120000")),
144
+ Select("domain", ["g"]),
145
+ Select("expver", ["0001"]),
146
+ Select("param", ["167"]),
147
+ Select("class", ["od"]),
148
+ Select("stream", ["oper"]),
149
+ Select("type", ["an"]),
150
+ Union(
151
+ ["longitude", "latitude"],
152
+ Point(["longitude", "latitude"], [[30, 25]], method="nearest"),
153
+ ),
154
+ )
155
+
156
+ self.fdbdatacube = gj.GribJump()
157
+ self.slicer = HullSlicer()
158
+ self.API = Polytope(
159
+ datacube=self.fdbdatacube,
160
+ engine=self.slicer,
161
+ options=self.options,
162
+ )
163
+ result = self.API.retrieve(request)
164
+ inverted_result = self.API.retrieve(inverted_request)
165
+ result.pprint()
166
+ inverted_result.pprint()
167
+ assert len(result.leaves) == 1
168
+ assert len(inverted_result.leaves) == 1
169
+ assert inverted_result.leaves[0].result == result.leaves[0].result
170
+
171
+ # @pytest.mark.fdb
172
+ # def test_fdb_datacube_mix_methods(self):
173
+ # import pygribjump as gj
174
+
175
+ # request = Request(
176
+ # Select("step", [0]),
177
+ # Select("levtype", ["sfc"]),
178
+ # Span("date", pd.Timestamp("20230625T120000"), pd.Timestamp("20230626T120000")),
179
+ # Select("domain", ["g"]),
180
+ # Select("expver", ["0001"]),
181
+ # Select("param", ["167"]),
182
+ # Select("class", ["od"]),
183
+ # Select("stream", ["oper"]),
184
+ # Select("type", ["an"]),
185
+ # Union(["latitude", "longitude"],
186
+ # Point(["latitude", "longitude"], [[25, 30]], method="nearest"),
187
+ # Point(["latitude", "longitude"], [[-15, -45]], method="surrounding"))
188
+ # )
189
+
190
+ # self.fdbdatacube = gj.GribJump()
191
+ # self.slicer = HullSlicer()
192
+ # self.API = Polytope(
193
+ # datacube=self.fdbdatacube,
194
+ # engine=self.slicer,
195
+ # options=self.options,
196
+ # )
197
+ # result = self.API.retrieve(request)
198
+ # result.pprint()
199
+ # assert len(result.leaves) == 6
@@ -1 +0,0 @@
1
- __version__ = "1.0.35"