polytope-python 1.0.4__tar.gz → 1.0.6__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 (58) hide show
  1. {polytope-python-1.0.4/polytope_python.egg-info → polytope-python-1.0.6}/PKG-INFO +1 -1
  2. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/backends/fdb.py +8 -6
  3. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/tensor_index_tree.py +7 -3
  4. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/engine/hullslicer.py +20 -4
  5. polytope-python-1.0.6/polytope/options.py +79 -0
  6. polytope-python-1.0.6/polytope/version.py +1 -0
  7. {polytope-python-1.0.4 → polytope-python-1.0.6/polytope_python.egg-info}/PKG-INFO +1 -1
  8. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope_python.egg-info/requires.txt +1 -1
  9. {polytope-python-1.0.4 → polytope-python-1.0.6}/requirements.txt +1 -1
  10. polytope-python-1.0.4/polytope/options.py +0 -71
  11. polytope-python-1.0.4/polytope/version.py +0 -1
  12. {polytope-python-1.0.4 → polytope-python-1.0.6}/LICENSE +0 -0
  13. {polytope-python-1.0.4 → polytope-python-1.0.6}/MANIFEST.in +0 -0
  14. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/__init__.py +0 -0
  15. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/__init__.py +0 -0
  16. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/backends/__init__.py +0 -0
  17. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/backends/datacube.py +0 -0
  18. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/backends/mock.py +0 -0
  19. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/backends/xarray.py +0 -0
  20. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/datacube_axis.py +0 -0
  21. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/index_tree_pb2.py +0 -0
  22. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/__init__.py +0 -0
  23. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_cyclic/__init__.py +0 -0
  24. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
  25. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/__init__.py +0 -0
  26. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/datacube_mappers.py +0 -0
  27. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -0
  28. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix.py +0 -0
  29. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +0 -0
  30. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +0 -0
  31. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +0 -0
  32. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +0 -0
  33. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_mappers/mapper_types/regular.py +0 -0
  34. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_merger/__init__.py +0 -0
  35. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_merger/datacube_merger.py +0 -0
  36. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_reverse/__init__.py +0 -0
  37. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
  38. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_transformations.py +0 -0
  39. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_type_change/__init__.py +0 -0
  40. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/transformations/datacube_type_change/datacube_type_change.py +0 -0
  41. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/datacube/tree_encoding.py +0 -0
  42. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/engine/__init__.py +0 -0
  43. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/engine/engine.py +0 -0
  44. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/polytope.py +0 -0
  45. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/shapes.py +0 -0
  46. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/__init__.py +0 -0
  47. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/combinatorics.py +0 -0
  48. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/exceptions.py +0 -0
  49. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/geometry.py +0 -0
  50. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/list_tools.py +0 -0
  51. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope/utility/profiling.py +0 -0
  52. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope_python.egg-info/SOURCES.txt +0 -0
  53. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope_python.egg-info/dependency_links.txt +0 -0
  54. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope_python.egg-info/not-zip-safe +0 -0
  55. {polytope-python-1.0.4 → polytope-python-1.0.6}/polytope_python.egg-info/top_level.txt +0 -0
  56. {polytope-python-1.0.4 → polytope-python-1.0.6}/pyproject.toml +0 -0
  57. {polytope-python-1.0.4 → polytope-python-1.0.6}/setup.cfg +0 -0
  58. {polytope-python-1.0.4 → polytope-python-1.0.6}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: polytope-python
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -55,7 +55,7 @@ class FDBDatacube(Datacube):
55
55
  val = self._axes[name].type
56
56
  self._check_and_add_axes(options, name, val)
57
57
 
58
- logging.info("Polytope created axes for: " + str(self._axes.keys()))
58
+ logging.info("Polytope created axes for %s", self._axes.keys())
59
59
 
60
60
  def check_branching_axes(self, request):
61
61
  polytopes = request.polytopes()
@@ -78,6 +78,7 @@ class FDBDatacube(Datacube):
78
78
  self._axes.pop(axis_name, None)
79
79
 
80
80
  def get(self, requests: TensorIndexTree):
81
+ requests.pprint()
81
82
  if len(requests.children) == 0:
82
83
  return requests
83
84
  fdb_requests = []
@@ -85,12 +86,9 @@ class FDBDatacube(Datacube):
85
86
  self.get_fdb_requests(requests, fdb_requests, fdb_requests_decoding_info)
86
87
 
87
88
  # here, loop through the fdb requests and request from gj and directly add to the nodes
88
-
89
- # TODO: here, loop through the fdb requests and request from gj and directly add to the nodes
90
89
  complete_list_complete_uncompressed_requests = []
91
90
  complete_fdb_decoding_info = []
92
91
  for j, compressed_request in enumerate(fdb_requests):
93
- # TODO: can we do gj extract outside of this loop?
94
92
  uncompressed_request = {}
95
93
 
96
94
  # Need to determine the possible decompressed requests
@@ -109,7 +107,9 @@ class FDBDatacube(Datacube):
109
107
  complete_uncompressed_request = (uncompressed_request, compressed_request[1])
110
108
  complete_list_complete_uncompressed_requests.append(complete_uncompressed_request)
111
109
  complete_fdb_decoding_info.append(fdb_requests_decoding_info[j])
110
+ logging.debug("The requests we give GribJump are: %s", complete_list_complete_uncompressed_requests)
112
111
  output_values = self.gj.extract(complete_list_complete_uncompressed_requests)
112
+ logging.debug("GribJump outputs: %s", output_values)
113
113
  self.assign_fdb_output_to_nodes(output_values, complete_fdb_decoding_info)
114
114
 
115
115
  def get_fdb_requests(
@@ -124,7 +124,7 @@ class FDBDatacube(Datacube):
124
124
 
125
125
  # First when request node is root, go to its children
126
126
  if requests.axis.name == "root":
127
- logging.info("Looking for data for the tree: " + str([leaf.flatten() for leaf in requests.leaves]))
127
+ logging.info("Looking for data for the tree: %s", [leaf.flatten() for leaf in requests.leaves])
128
128
 
129
129
  for c in requests.children:
130
130
  self.get_fdb_requests(c, fdb_requests, fdb_requests_decoding_info)
@@ -162,7 +162,7 @@ class FDBDatacube(Datacube):
162
162
  for j, idx in enumerate(sub_lat_idxs):
163
163
  if idx not in seen_indices:
164
164
  # TODO: need to remove it from the values in the corresponding tree node
165
- # TODO: need to readjust the range we give to gj ... DONE?
165
+ # TODO: need to read just the range we give to gj ... DONE?
166
166
  original_fdb_node_range_vals.append(actual_fdb_node[0].values[j])
167
167
  seen_indices.add(idx)
168
168
  new_current_start_idx.append(idx)
@@ -325,6 +325,8 @@ class FDBDatacube(Datacube):
325
325
  request_ranges_with_idx = list(enumerate(interm_request_ranges))
326
326
  sorted_list = sorted(request_ranges_with_idx, key=lambda x: x[1][0])
327
327
  original_indices, sorted_request_ranges = zip(*sorted_list)
328
+ logging.debug("We sorted the request ranges into: %s", sorted_request_ranges)
329
+ logging.debug("The sorted and unique leaf node ranges are: %s", new_fdb_node_ranges)
328
330
  return (original_indices, sorted_request_ranges, new_fdb_node_ranges)
329
331
 
330
332
  def datacube_natural_indexes(self, axis, subarray):
@@ -81,8 +81,12 @@ class TensorIndexTree(object):
81
81
  for i in range(len(other.values)):
82
82
  other_val = other.values[i]
83
83
  self_val = self.values[i]
84
- if abs(other_val - self_val) > 2 * max(other.axis.tol, self.axis.tol):
85
- return False
84
+ if self.axis.can_round:
85
+ if abs(other_val - self_val) > 2 * max(other.axis.tol, self.axis.tol):
86
+ return False
87
+ else:
88
+ if other_val != self_val:
89
+ return False
86
90
  return True
87
91
 
88
92
  def __lt__(self, other):
@@ -217,7 +221,7 @@ class TensorIndexTree(object):
217
221
  def get_ancestors(self):
218
222
  ancestors = []
219
223
  current_node = self
220
- while current_node.axis != TensorIndexTree.root:
224
+ while current_node.axis.name != "root":
221
225
  ancestors.append(current_node)
222
226
  current_node = current_node.parent
223
227
  return ancestors[::-1]
@@ -91,7 +91,7 @@ class HullSlicer(Engine):
91
91
  flattened = {flattened_tuple[0]: flattened_tuple[1]}
92
92
 
93
93
  values = self.axis_values_between.get((flattened_tuple, ax.name, lower, upper, method), None)
94
- if self.axis_values_between.get((flattened_tuple, ax.name, lower, upper, method), None) is None:
94
+ if values is None:
95
95
  values = datacube.get_indices(flattened, ax, lower, upper, method)
96
96
  self.axis_values_between[(flattened_tuple, ax.name, lower, upper, method)] = values
97
97
  return values
@@ -109,9 +109,6 @@ class HullSlicer(Engine):
109
109
  return remapped_val
110
110
 
111
111
  def _build_sliceable_child(self, polytope, ax, node, datacube, values, next_nodes, slice_axis_idx):
112
- if len(values) == 0:
113
- node.remove_branch()
114
-
115
112
  for i, value in enumerate(values):
116
113
  if i == 0:
117
114
  fvalue = ax.to_float(value)
@@ -140,8 +137,16 @@ class HullSlicer(Engine):
140
137
 
141
138
  def _build_branch(self, ax, node, datacube, next_nodes):
142
139
  if ax.name not in self.compressed_axes:
140
+ parent_node = node.parent
141
+ right_unsliced_polytopes = []
143
142
  for polytope in node["unsliced_polytopes"]:
144
143
  if ax.name in polytope._axes:
144
+ right_unsliced_polytopes.append(polytope)
145
+ # for polytope in node["unsliced_polytopes"]:
146
+ for i, polytope in enumerate(right_unsliced_polytopes):
147
+ node._parent = parent_node
148
+ # if ax.name in polytope._axes:
149
+ if True:
145
150
  lower, upper, slice_axis_idx = polytope.extents(ax.name)
146
151
  # here, first check if the axis is an unsliceable axis and directly build node if it is
147
152
  # NOTE: we should have already created the ax_is_unsliceable cache before
@@ -149,13 +154,22 @@ class HullSlicer(Engine):
149
154
  self._build_unsliceable_child(polytope, ax, node, datacube, [lower], next_nodes, slice_axis_idx)
150
155
  else:
151
156
  values = self.find_values_between(polytope, ax, node, datacube, lower, upper)
157
+ # NOTE: need to only remove the branches if the values are empty,
158
+ # but only if there are no other possible children left in the tree that
159
+ # we can append and if somehow this happens before and we need to remove, then what do we do??
160
+ if i == len(right_unsliced_polytopes) - 1:
161
+ # we have iterated all polytopes and we can now remove the node if we need to
162
+ if len(values) == 0 and len(node.children) == 0:
163
+ node.remove_branch()
152
164
  self._build_sliceable_child(polytope, ax, node, datacube, values, next_nodes, slice_axis_idx)
153
165
  else:
154
166
  all_values = []
155
167
  all_lowers = []
156
168
  first_polytope = False
157
169
  first_slice_axis_idx = False
170
+ parent_node = node.parent
158
171
  for polytope in node["unsliced_polytopes"]:
172
+ node._parent = parent_node
159
173
  if ax.name in polytope._axes:
160
174
  # keep track of the first polytope defined on the given axis
161
175
  if not first_polytope:
@@ -173,6 +187,8 @@ class HullSlicer(Engine):
173
187
  first_polytope, ax, node, datacube, all_lowers, next_nodes, first_slice_axis_idx
174
188
  )
175
189
  else:
190
+ if len(all_values) == 0:
191
+ node.remove_branch()
176
192
  self._build_sliceable_child(
177
193
  first_polytope, ax, node, datacube, all_values, next_nodes, first_slice_axis_idx
178
194
  )
@@ -0,0 +1,79 @@
1
+ import argparse
2
+ from abc import ABC
3
+ from typing import Dict, List, Literal, Optional, Union
4
+
5
+ from conflator import ConfigModel, Conflator
6
+ from pydantic import ConfigDict
7
+
8
+
9
+ class TransformationConfig(ConfigModel):
10
+ model_config = ConfigDict(extra="forbid")
11
+ name: str = ""
12
+
13
+
14
+ class CyclicConfig(TransformationConfig):
15
+ name: Literal["cyclic"]
16
+ range: List[float] = [0]
17
+
18
+
19
+ class MapperConfig(TransformationConfig):
20
+ name: Literal["mapper"]
21
+ type: str = ""
22
+ resolution: Union[int, List[int]] = 0
23
+ axes: List[str] = [""]
24
+ local: Optional[List[float]] = None
25
+
26
+
27
+ class ReverseConfig(TransformationConfig):
28
+ name: Literal["reverse"]
29
+ is_reverse: bool = False
30
+
31
+
32
+ class TypeChangeConfig(TransformationConfig):
33
+ name: Literal["type_change"]
34
+ type: str = "int"
35
+
36
+
37
+ class MergeConfig(TransformationConfig):
38
+ name: Literal["merge"]
39
+ other_axis: str = ""
40
+ linkers: List[str] = [""]
41
+
42
+
43
+ action_subclasses_union = Union[CyclicConfig, MapperConfig, ReverseConfig, TypeChangeConfig, MergeConfig]
44
+
45
+
46
+ class AxisConfig(ConfigModel):
47
+ axis_name: str = ""
48
+ transformations: list[action_subclasses_union]
49
+
50
+
51
+ path_subclasses_union = Union[str, int, float]
52
+
53
+
54
+ class GribJumpAxesConfig(ConfigModel):
55
+ axis_name: str = ""
56
+ values: List[str] = [""]
57
+
58
+
59
+ class Config(ConfigModel):
60
+ axis_config: List[AxisConfig] = []
61
+ compressed_axes_config: List[str] = [""]
62
+ pre_path: Optional[Dict[str, path_subclasses_union]] = {}
63
+ alternative_axes: List[GribJumpAxesConfig] = []
64
+
65
+
66
+ class PolytopeOptions(ABC):
67
+ @staticmethod
68
+ def get_polytope_options(options):
69
+
70
+ parser = argparse.ArgumentParser(allow_abbrev=False)
71
+ conflator = Conflator(app_name="polytope", model=Config, cli=False, argparser=parser, **options)
72
+ config_options = conflator.load()
73
+
74
+ axis_config = config_options.axis_config
75
+ compressed_axes_config = config_options.compressed_axes_config
76
+ pre_path = config_options.pre_path
77
+ alternative_axes = config_options.alternative_axes
78
+
79
+ return (axis_config, compressed_axes_config, pre_path, alternative_axes)
@@ -0,0 +1 @@
1
+ __version__ = "1.0.6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: polytope-python
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -4,5 +4,5 @@ scipy
4
4
  sortedcontainers
5
5
  tripy
6
6
  xarray
7
- conflator@ git+https://github.com/ecmwf/conflator.git@main
7
+ conflator
8
8
  protobuf
@@ -4,5 +4,5 @@ scipy
4
4
  sortedcontainers
5
5
  tripy
6
6
  xarray
7
- conflator @ git+https://github.com/ecmwf/conflator.git@main
7
+ conflator
8
8
  protobuf
@@ -1,71 +0,0 @@
1
- import argparse
2
- from abc import ABC
3
- from typing import Dict, List, Literal, Optional, Union
4
-
5
- from conflator import ConfigModel, Conflator
6
- from pydantic import ConfigDict
7
-
8
-
9
- class PolytopeOptions(ABC):
10
- @staticmethod
11
- def get_polytope_options(options):
12
- class TransformationConfig(ConfigModel):
13
- model_config = ConfigDict(extra="forbid")
14
- name: str = ""
15
-
16
- class CyclicConfig(TransformationConfig):
17
- name: Literal["cyclic"]
18
- range: List[float] = [0]
19
-
20
- class MapperConfig(TransformationConfig):
21
- name: Literal["mapper"]
22
- type: str = ""
23
- resolution: Union[int, List[int]] = 0
24
- axes: List[str] = [""]
25
- local: Optional[List[float]] = None
26
-
27
- class ReverseConfig(TransformationConfig):
28
- name: Literal["reverse"]
29
- is_reverse: bool = False
30
-
31
- class TypeChangeConfig(TransformationConfig):
32
- name: Literal["type_change"]
33
- type: str = "int"
34
-
35
- class MergeConfig(TransformationConfig):
36
- name: Literal["merge"]
37
- other_axis: str = ""
38
- linkers: List[str] = [""]
39
-
40
- action_subclasses_union = Union[CyclicConfig, MapperConfig, ReverseConfig, TypeChangeConfig, MergeConfig]
41
-
42
- class AxisConfig(ConfigModel):
43
- axis_name: str = ""
44
- transformations: list[action_subclasses_union]
45
-
46
- path_subclasses_union = Union[str, int, float]
47
-
48
- class GribJumpAxesConfig(ConfigModel):
49
- axis_name: str = ""
50
- values: List[str] = [""]
51
-
52
- class Config(ConfigModel):
53
- axis_config: List[AxisConfig] = []
54
- compressed_axes_config: List[str] = [""]
55
- pre_path: Optional[Dict[str, path_subclasses_union]] = {}
56
- alternative_axes: List[GribJumpAxesConfig] = []
57
-
58
- parser = argparse.ArgumentParser(allow_abbrev=False)
59
- config_options = Conflator(app_name="polytope", model=Config, cli=False, argparser=parser).load()
60
- config_options = Config(
61
- axis_config=options.get("axis_config", []),
62
- compressed_axes_config=options.get("compressed_axes_config", [""]),
63
- pre_path=options.get("pre_path", {}),
64
- alternative_axes=options.get("alternative_axes", []),
65
- )
66
- axis_config = config_options.axis_config
67
- compressed_axes_config = config_options.compressed_axes_config
68
- pre_path = config_options.pre_path
69
- alternative_axes = config_options.alternative_axes
70
-
71
- return (axis_config, compressed_axes_config, pre_path, alternative_axes)
@@ -1 +0,0 @@
1
- __version__ = "1.0.4"
File without changes