polytope-python 1.0.34__tar.gz → 1.0.35__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 (119) hide show
  1. {polytope_python-1.0.34/polytope_python.egg-info → polytope_python-1.0.35}/PKG-INFO +1 -1
  2. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py +3 -5
  3. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py +8 -5
  4. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +36 -46
  5. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +8 -5
  6. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +10 -7
  7. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_gaussian.py +8 -16
  8. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +8 -5
  9. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py +8 -5
  10. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/tree_encoding.py +2 -1
  11. polytope_python-1.0.35/polytope_feature/version.py +1 -0
  12. {polytope_python-1.0.34 → polytope_python-1.0.35/polytope_python.egg-info}/PKG-INFO +1 -1
  13. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_fdb_unmap_tree.py +9 -9
  14. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_healpix_mapper.py +1 -1
  15. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_mappers.py +3 -3
  16. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_regular_grid.py +1 -1
  17. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_regular_reduced_grid.py +3 -0
  18. polytope_python-1.0.34/polytope_feature/version.py +0 -1
  19. {polytope_python-1.0.34 → polytope_python-1.0.35}/LICENSE +0 -0
  20. {polytope_python-1.0.34 → polytope_python-1.0.35}/MANIFEST.in +0 -0
  21. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/__init__.py +0 -0
  22. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/__init__.py +0 -0
  23. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/backends/__init__.py +0 -0
  24. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/backends/datacube.py +0 -0
  25. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/backends/fdb.py +0 -0
  26. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/backends/mock.py +0 -0
  27. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/backends/xarray.py +0 -0
  28. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/datacube_axis.py +0 -0
  29. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/index_tree_pb2.py +0 -0
  30. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/tensor_index_tree.py +0 -0
  31. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/__init__.py +0 -0
  32. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_cyclic/__init__.py +0 -0
  33. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
  34. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/__init__.py +0 -0
  35. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -0
  36. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_merger/__init__.py +0 -0
  37. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py +0 -0
  38. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_reverse/__init__.py +0 -0
  39. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
  40. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_transformations.py +0 -0
  41. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_type_change/__init__.py +0 -0
  42. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py +0 -0
  43. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/engine/__init__.py +0 -0
  44. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/engine/engine.py +0 -0
  45. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/engine/hullslicer.py +0 -0
  46. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/options.py +0 -0
  47. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/polytope.py +0 -0
  48. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/shapes.py +0 -0
  49. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/__init__.py +0 -0
  50. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/combinatorics.py +0 -0
  51. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/exceptions.py +0 -0
  52. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/geometry.py +0 -0
  53. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/list_tools.py +0 -0
  54. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_feature/utility/profiling.py +0 -0
  55. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_python.egg-info/SOURCES.txt +0 -0
  56. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_python.egg-info/dependency_links.txt +0 -0
  57. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_python.egg-info/not-zip-safe +0 -0
  58. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_python.egg-info/requires.txt +0 -0
  59. {polytope_python-1.0.34 → polytope_python-1.0.35}/polytope_python.egg-info/top_level.txt +0 -0
  60. {polytope_python-1.0.34 → polytope_python-1.0.35}/pyproject.toml +0 -0
  61. {polytope_python-1.0.34 → polytope_python-1.0.35}/requirements.txt +0 -0
  62. {polytope_python-1.0.34 → polytope_python-1.0.35}/setup.cfg +0 -0
  63. {polytope_python-1.0.34 → polytope_python-1.0.35}/setup.py +0 -0
  64. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_axis_mappers.py +0 -0
  65. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_bad_request_error.py +0 -0
  66. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_combinatorics.py +0 -0
  67. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_axis_over_negative_vals.py +0 -0
  68. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_axis_slicer_not_0.py +0 -0
  69. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_axis_slicing.py +0 -0
  70. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_nearest.py +0 -0
  71. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_simple.py +0 -0
  72. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_cyclic_snapping.py +0 -0
  73. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_datacube_axes_init.py +0 -0
  74. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_datacube_mock.py +0 -0
  75. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_datacube_xarray.py +0 -0
  76. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_date_time_unmerged.py +0 -0
  77. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_ecmwf_oper_data_fdb.py +0 -0
  78. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_engine_slicer.py +0 -0
  79. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_fdb_datacube.py +0 -0
  80. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_float_type.py +0 -0
  81. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_healpix_nested_grid.py +0 -0
  82. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_hull_slicer.py +0 -0
  83. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_hullslicer_engine.py +0 -0
  84. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_incomplete_tree_fdb.py +0 -0
  85. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_local_grid_cyclic.py +0 -0
  86. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_local_regular_grid.py +0 -0
  87. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_local_swiss_grid.py +0 -0
  88. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_merge_cyclic_octahedral.py +0 -0
  89. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_merge_octahedral_one_axis.py +0 -0
  90. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_merge_transformation.py +0 -0
  91. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_multiple_param_fdb.py +0 -0
  92. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_octahedral_grid.py +0 -0
  93. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_override_md5_hash_options.py +0 -0
  94. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_point_nearest.py +0 -0
  95. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_point_shape.py +0 -0
  96. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_profiling_requesttree.py +0 -0
  97. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_reduced_ll_grid.py +0 -0
  98. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_request_tree.py +0 -0
  99. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_request_trees_after_slicing.py +0 -0
  100. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_reverse_transformation.py +0 -0
  101. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_shapes.py +0 -0
  102. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slice_date_range_fdb.py +0 -0
  103. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slice_date_range_fdb_v2.py +0 -0
  104. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slice_fdb_box.py +0 -0
  105. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicer_engine.py +0 -0
  106. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicer_era5.py +0 -0
  107. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicer_xarray.py +0 -0
  108. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicing_unsliceable_axis.py +0 -0
  109. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicing_xarray_3D.py +0 -0
  110. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_slicing_xarray_4D.py +0 -0
  111. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_snapping.py +0 -0
  112. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_snapping_real_data.py +0 -0
  113. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_tree_protobuf.py +0 -0
  114. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_tree_protobuf_encoding.py +0 -0
  115. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_tree_protobuf_encoding_fdb.py +0 -0
  116. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_type_change_transformation.py +0 -0
  117. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_union_gj.py +0 -0
  118. {polytope_python-1.0.34 → polytope_python-1.0.35}/tests/test_union_point_box.py +0 -0
  119. {polytope_python-1.0.34 → polytope_python-1.0.35}/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.34
3
+ Version: 1.0.35
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -99,16 +99,14 @@ class DatacubeMapper(DatacubeAxisTransformation):
99
99
  return self.second_axis_vals(first_val)
100
100
 
101
101
  def unmap_path_key(self, key_value_path, leaf_path, unwanted_path, axis):
102
- value = key_value_path[axis.name]
102
+ values = key_value_path[axis.name]
103
103
  if axis.name == self._mapped_axes()[0]:
104
104
  unwanted_val = key_value_path[self._mapped_axes()[0]]
105
105
  unwanted_path[axis.name] = unwanted_val
106
106
  if axis.name == self._mapped_axes()[1]:
107
107
  first_val = unwanted_path[self._mapped_axes()[0]]
108
- unmapped_idx = []
109
- for val in value:
110
- unmapped_idx.append(self.unmap(first_val, (val,)))
111
- # unmapped_idx = self.unmap(first_val, value)
108
+ # unmapped_idx = [self.unmap(first_val, (val,)) for val in value]
109
+ unmapped_idx = self.unmap(first_val, values)
112
110
  leaf_path.pop(self._mapped_axes()[0], None)
113
111
  key_value_path.pop(axis.name)
114
112
  key_value_path[self.old_axis] = unmapped_idx
@@ -133,14 +133,17 @@ class HealpixGridMapper(DatacubeMapper):
133
133
  else:
134
134
  return idx
135
135
 
136
- def unmap(self, first_val, second_val):
136
+ def unmap(self, first_val, second_vals):
137
137
  tol = 1e-8
138
138
  first_value = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
139
139
  first_idx = self._first_axis_vals.index(first_value)
140
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
141
- second_idx = self.second_axis_vals(first_val).index(second_val)
142
- healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx)
143
- return healpix_index
140
+ return_idxs = []
141
+ for second_val in second_vals:
142
+ second_val = [i for i in self.second_axis_vals(first_val) if second_val - tol <= i <= second_val + tol][0]
143
+ second_idx = self.second_axis_vals(first_val).index(second_val)
144
+ healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx)
145
+ return_idxs.append(healpix_index)
146
+ return return_idxs
144
147
 
145
148
 
146
149
  # md5 grid hash in form {resolution : hash}
@@ -1,4 +1,3 @@
1
- import bisect
2
1
  import math
3
2
 
4
3
  from ..datacube_mappers import DatacubeMapper
@@ -14,9 +13,11 @@ class NestedHealpixGridMapper(DatacubeMapper):
14
13
  self._first_axis_vals = self.first_axis_vals()
15
14
  self.compressed_grid_axes = [self._mapped_axes[1]]
16
15
  self.Nside = self._resolution
16
+ self._cached_longitudes = {}
17
17
  self.k = int(math.log2(self.Nside))
18
18
  self.Npix = 12 * self.Nside * self.Nside
19
19
  self.Ncap = (self.Nside * (self.Nside - 1)) << 1
20
+ self._healpix_longitudes = {}
20
21
  if md5_hash is not None:
21
22
  self.md5_hash = md5_hash
22
23
  else:
@@ -58,7 +59,9 @@ class NestedHealpixGridMapper(DatacubeMapper):
58
59
  return values
59
60
 
60
61
  def second_axis_vals_from_idx(self, first_val_idx):
61
- values = self.HEALPix_longitudes(first_val_idx)
62
+ if first_val_idx not in self._healpix_longitudes:
63
+ self._healpix_longitudes[first_val_idx] = self.HEALPix_longitudes(first_val_idx)
64
+ values = self._healpix_longitudes[first_val_idx]
62
65
  return values
63
66
 
64
67
  def HEALPix_nj(self, i):
@@ -74,14 +77,19 @@ class NestedHealpixGridMapper(DatacubeMapper):
74
77
  return self.HEALPix_nj(ni - 1 - i)
75
78
 
76
79
  def HEALPix_longitudes(self, i):
77
- Nj = self.HEALPix_nj(i)
78
- step = 360.0 / Nj
79
- start = (
80
- step / 2.0 if i < self._resolution or 3 * self._resolution - 1 < i or (i + self._resolution) % 2 else 0.0
81
- )
82
-
83
- longitudes = [start + n * step for n in range(Nj)]
84
-
80
+ if i in self._cached_longitudes:
81
+ return self._cached_longitudes[i]
82
+ else:
83
+ Nj = self.HEALPix_nj(i)
84
+ step = 360.0 / Nj
85
+ start = (
86
+ step / 2.0
87
+ if i < self._resolution or 3 * self._resolution - 1 < i or (i + self._resolution) % 2
88
+ else 0.0
89
+ )
90
+
91
+ longitudes = [start + n * step for n in range(Nj)]
92
+ self._cached_longitudes[i] = longitudes
85
93
  return longitudes
86
94
 
87
95
  def map_second_axis(self, first_val, lower, upper):
@@ -110,43 +118,25 @@ class NestedHealpixGridMapper(DatacubeMapper):
110
118
  idx += second_idx
111
119
  return idx
112
120
 
113
- def find_second_idx(self, first_val, second_val):
114
- tol = 1e-10
115
- second_axis_vals = self.second_axis_vals(first_val)
116
- second_idx = bisect.bisect_left(second_axis_vals, second_val - tol)
117
- return second_idx
118
-
119
- def unmap_first_val_to_start_line_idx(self, first_val):
120
- tol = 1e-8
121
- first_val = [i for i in self._first_axis_vals if first_val - tol <= i <= first_val + tol][0]
122
- first_idx = self._first_axis_vals.index(first_val)
123
- idx = 0
124
- for i in range(self._resolution - 1):
125
- if i != first_idx:
126
- idx += 4 * (i + 1)
127
- else:
128
- return idx
129
- for i in range(self._resolution - 1, 3 * self._resolution):
130
- if i != first_idx:
131
- idx += 4 * self._resolution
132
- else:
133
- return idx
134
- for i in range(3 * self._resolution, 4 * self._resolution - 1):
135
- if i != first_idx:
136
- idx += 4 * (4 * self._resolution - 1 - i + 1)
137
- else:
138
- return idx
139
-
140
- def unmap(self, first_val, second_val):
121
+ def unmap(self, first_val, second_vals):
141
122
  tol = 1e-8
142
- first_value = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
143
- first_idx = self._first_axis_vals.index(first_value)
144
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
145
- second_idx = self.second_axis_vals(first_val).index(second_val)
146
- healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx)
147
- # TODO: here do conversion of ring to nested healpix representation before returning
148
- healpix_index = self.ring_to_nested(healpix_index)
149
- return healpix_index
123
+ first_idx = next(
124
+ (i for i, val in enumerate(self._first_axis_vals) if first_val[0] - tol <= val <= first_val[0] + tol), None
125
+ )
126
+ if first_idx is None:
127
+ return None
128
+ second_axis_vals = self.second_axis_vals_from_idx(first_idx)
129
+
130
+ return_idxs = []
131
+ for second_val in second_vals:
132
+ second_idx = next(
133
+ (i for i, val in enumerate(second_axis_vals) if second_val - tol <= val <= second_val + tol), None
134
+ )
135
+ if second_idx is None:
136
+ return None
137
+ healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx)
138
+ return_idxs.append(healpix_index)
139
+ return return_idxs
150
140
 
151
141
  def div_03(self, a, b):
152
142
  t = 1 if a >= (b << 1) else 0
@@ -81,14 +81,17 @@ class LocalRegularGridMapper(DatacubeMapper):
81
81
  first_idx = self._first_axis_vals.index(first_val)
82
82
  return first_idx * self.second_resolution
83
83
 
84
- def unmap(self, first_val, second_val):
84
+ def unmap(self, first_val, second_vals):
85
85
  tol = 1e-8
86
86
  first_val = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
87
87
  first_idx = self._first_axis_vals.index(first_val)
88
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
89
- second_idx = self.second_axis_vals(first_val).index(second_val)
90
- final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
91
- return final_index
88
+ return_idxs = []
89
+ for second_val in second_vals:
90
+ second_val = [i for i in self.second_axis_vals(first_val) if second_val - tol <= i <= second_val + tol][0]
91
+ second_idx = self.second_axis_vals(first_val).index(second_val)
92
+ final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
93
+ return_idxs.append(final_index)
94
+ return return_idxs
92
95
 
93
96
 
94
97
  # md5 grid hash in form {resolution : hash}
@@ -7877,16 +7877,19 @@ class OctahedralGridMapper(DatacubeMapper):
7877
7877
  def find_second_axis_idx(self, first_val, second_val):
7878
7878
  (second_axis_spacing, first_idx) = self.second_axis_spacing(first_val)
7879
7879
  tol = 1e-8
7880
- if second_val[0] / second_axis_spacing > int(second_val[0] / second_axis_spacing) + 1 - tol:
7881
- second_idx = int(second_val[0] / second_axis_spacing) + 1
7880
+ if second_val / second_axis_spacing > int(second_val / second_axis_spacing) + 1 - tol:
7881
+ second_idx = int(second_val / second_axis_spacing) + 1
7882
7882
  else:
7883
- second_idx = int(second_val[0] / second_axis_spacing)
7883
+ second_idx = int(second_val / second_axis_spacing)
7884
7884
  return (first_idx, second_idx)
7885
7885
 
7886
- def unmap(self, first_val, second_val):
7887
- (first_idx, second_idx) = self.find_second_axis_idx(first_val, second_val)
7888
- octahedral_index = self.axes_idx_to_octahedral_idx(first_idx, second_idx)
7889
- return octahedral_index
7886
+ def unmap(self, first_val, second_vals):
7887
+ return_idxs = []
7888
+ for second_val in second_vals:
7889
+ (first_idx, second_idx) = self.find_second_axis_idx(first_val, second_val)
7890
+ octahedral_index = self.axes_idx_to_octahedral_idx(first_idx, second_idx)
7891
+ return_idxs.append(octahedral_index)
7892
+ return return_idxs
7890
7893
 
7891
7894
 
7892
7895
  # md5 grid hash in form {resolution : hash}
@@ -1432,25 +1432,17 @@ class ReducedGaussianGridMapper(DatacubeMapper):
1432
1432
  idx += second_idx
1433
1433
  return idx
1434
1434
 
1435
- # def find_second_idx(self, first_val, second_val):
1436
- # tol = 1e-10
1437
- # second_axis_vals = self.second_axis_vals(first_val)
1438
- # second_idx = bisect.bisect_left(second_axis_vals, second_val[0] - tol)
1439
- # return second_idx
1440
-
1441
- # def unmap(self, first_val, second_val):
1442
- # (first_idx, second_idx) = self.find_second_idx(first_val, second_val)
1443
- # octahedral_index = self.axes_idx_to_reduced_gaussian_idx(first_idx, second_idx)
1444
- # return octahedral_index
1445
-
1446
- def unmap(self, first_val, second_val):
1435
+ def unmap(self, first_val, second_vals):
1447
1436
  tol = 1e-8
1448
1437
  first_value = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
1449
1438
  first_idx = self._first_axis_vals.index(first_value)
1450
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
1451
- second_idx = self.second_axis_vals(first_val).index(second_val)
1452
- reduced_gaussian_index = self.axes_idx_to_reduced_gaussian_idx(first_idx, second_idx)
1453
- return reduced_gaussian_index
1439
+ return_idxs = []
1440
+ for second_val in second_vals:
1441
+ second_val = [i for i in self.second_axis_vals(first_val) if second_val - tol <= i <= second_val + tol][0]
1442
+ second_idx = self.second_axis_vals(first_val).index(second_val)
1443
+ reduced_gaussian_index = self.axes_idx_to_reduced_gaussian_idx(first_idx, second_idx)
1444
+ return_idxs.append(reduced_gaussian_index)
1445
+ return return_idxs
1454
1446
 
1455
1447
 
1456
1448
  # md5 grid hash in form {resolution : hash}
@@ -5114,14 +5114,17 @@ class ReducedLatLonMapper(DatacubeMapper):
5114
5114
  second_idx = bisect.bisect_left(second_axis_vals, second_val - tol)
5115
5115
  return second_idx
5116
5116
 
5117
- def unmap(self, first_val, second_val):
5117
+ def unmap(self, first_val, second_vals):
5118
5118
  tol = 1e-8
5119
5119
  first_value = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
5120
5120
  first_idx = self._first_axis_vals.index(first_value)
5121
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
5122
- second_idx = self.second_axis_vals(first_val).index(second_val)
5123
- reduced_ll_index = self.axes_idx_to_reduced_ll_idx(first_idx, second_idx)
5124
- return reduced_ll_index
5121
+ return_idxs = []
5122
+ for second_val in second_vals:
5123
+ second_val = [i for i in self.second_axis_vals(first_val) if second_val - tol <= i <= second_val + tol][0]
5124
+ second_idx = self.second_axis_vals(first_val).index(second_val)
5125
+ reduced_ll_index = self.axes_idx_to_reduced_ll_idx(first_idx, second_idx)
5126
+ return_idxs.append(reduced_ll_index)
5127
+ return return_idxs
5125
5128
 
5126
5129
 
5127
5130
  # md5 grid hash in form {resolution : hash}
@@ -61,14 +61,17 @@ class RegularGridMapper(DatacubeMapper):
61
61
  first_idx = self._first_axis_vals.index(first_val)
62
62
  return first_idx * 4 * self._resolution
63
63
 
64
- def unmap(self, first_val, second_val):
64
+ def unmap(self, first_val, second_vals):
65
65
  tol = 1e-8
66
66
  first_val = [i for i in self._first_axis_vals if first_val[0] - tol <= i <= first_val[0] + tol][0]
67
67
  first_idx = self._first_axis_vals.index(first_val)
68
- second_val = [i for i in self.second_axis_vals(first_val) if second_val[0] - tol <= i <= second_val[0] + tol][0]
69
- second_idx = self.second_axis_vals(first_val).index(second_val)
70
- final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
71
- return final_index
68
+ return_idxs = []
69
+ for second_val in second_vals:
70
+ second_val = [i for i in self.second_axis_vals(first_val) if second_val - tol <= i <= second_val + tol][0]
71
+ second_idx = self.second_axis_vals(first_val).index(second_val)
72
+ final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
73
+ return_idxs.append(final_index)
74
+ return return_idxs
72
75
 
73
76
 
74
77
  # md5 grid hash in form {resolution : hash}
@@ -38,7 +38,8 @@ def encode_child(tree: TensorIndexTree, child: TensorIndexTree, node, result_siz
38
38
 
39
39
  if child.hidden:
40
40
  # add indexes to parent and add also indexes size...
41
- node.indexes.extend(tree.indexes)
41
+ for tree_indexes in tree.indexes:
42
+ node.indexes.extend(tree_indexes)
42
43
  break_tag = False
43
44
  return break_tag
44
45
 
@@ -0,0 +1 @@
1
+ __version__ = "1.0.35"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polytope-python
3
- Version: 1.0.34
3
+ Version: 1.0.35
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -73,13 +73,13 @@ class TestSlicingFDBDatacube:
73
73
  assert leaf.hidden
74
74
  assert leaf._parent.hidden
75
75
  assert leaf._parent._parent.indexes == [
76
- 3294704,
77
- 3294705,
78
- 3294706,
79
- 3289572,
80
- 3289573,
81
- 3289574,
82
- 3284444,
83
- 3284445,
84
- 3284446,
76
+ [3294704],
77
+ [3294705],
78
+ [3294706],
79
+ [3289572],
80
+ [3289573],
81
+ [3289574],
82
+ [3284444],
83
+ [3284445],
84
+ [3284446],
85
85
  ]
@@ -70,7 +70,7 @@ class TestHealpixGrid:
70
70
  eccodes_result = nearest_points[0][0]["value"]
71
71
 
72
72
  mapper = HealpixGridMapper("base", ["base1", "base2"], 32)
73
- assert nearest_points[0][0]["index"] == mapper.unmap((lat,), (lon,))
73
+ assert nearest_points[0][0]["index"] == mapper.unmap((lat,), (lon,))[0]
74
74
  assert eccodes_lat - tol <= lat
75
75
  assert lat <= eccodes_lat + tol
76
76
  assert eccodes_lon - tol <= lon
@@ -102,6 +102,6 @@ class TestMapper:
102
102
  base_axis = "base"
103
103
  resolution = 1280
104
104
  octahedral_mapper = OctahedralGridMapper(base_axis, mapped_axes, resolution)
105
- assert octahedral_mapper.unmap((89.94618771566562,), (0,)) == 0
106
- assert octahedral_mapper.unmap((0.035149384215604956,), (0,)) == 3299840 - 5136
107
- assert octahedral_mapper.unmap((-0.035149384215604956,), (0,)) == 3299840
105
+ assert octahedral_mapper.unmap((89.94618771566562,), (0,))[0] == 0
106
+ assert octahedral_mapper.unmap((0.035149384215604956,), (0,))[0] == 3299840 - 5136
107
+ assert octahedral_mapper.unmap((-0.035149384215604956,), (0,))[0] == 3299840
@@ -116,7 +116,7 @@ class TestRegularGrid:
116
116
  eccodes_lats.append(eccodes_lat)
117
117
 
118
118
  mapper = RegularGridMapper("base", ["base1", "base2"], 30)
119
- assert nearest_points[121][0]["index"] == mapper.unmap((lat,), (lon,))
119
+ assert nearest_points[121][0]["index"] == mapper.unmap((lat,), (lon,))[0]
120
120
 
121
121
  assert eccodes_lat - tol <= lat
122
122
  assert lat <= eccodes_lat + tol
@@ -10,6 +10,8 @@ from polytope_feature.shapes import Box, Select
10
10
  class TestSlicingFDBDatacube:
11
11
  def setup_method(self, method):
12
12
  # Create a dataarray with 3 labelled axes using different index types
13
+ # TODO: This uses the wrong fdb/schema/data so the hash for the grid is wrong
14
+ # BUT the validation against eccodes is OK because the GRIB file is the same grid as Polytope returns
13
15
  self.options = {
14
16
  "axis_config": [
15
17
  {"axis_name": "step", "transformations": [{"name": "type_change", "type": "int"}]},
@@ -25,6 +27,7 @@ class TestSlicingFDBDatacube:
25
27
  "type": "reduced_gaussian",
26
28
  "resolution": 320,
27
29
  "axes": ["latitude", "longitude"],
30
+ "md5_hash": "158db321ae8e773681eeb40e0a3d350f",
28
31
  }
29
32
  ],
30
33
  },
@@ -1 +0,0 @@
1
- __version__ = "1.0.34"