polytope-python 1.0.31__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. polytope_feature/__init__.py +1 -0
  2. polytope_feature/datacube/__init__.py +1 -0
  3. polytope_feature/datacube/backends/__init__.py +1 -0
  4. polytope_feature/datacube/backends/datacube.py +171 -0
  5. polytope_feature/datacube/backends/fdb.py +399 -0
  6. polytope_feature/datacube/backends/mock.py +71 -0
  7. polytope_feature/datacube/backends/xarray.py +142 -0
  8. polytope_feature/datacube/datacube_axis.py +332 -0
  9. polytope_feature/datacube/index_tree_pb2.py +27 -0
  10. polytope_feature/datacube/tensor_index_tree.py +228 -0
  11. polytope_feature/datacube/transformations/__init__.py +1 -0
  12. polytope_feature/datacube/transformations/datacube_cyclic/__init__.py +1 -0
  13. polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py +171 -0
  14. polytope_feature/datacube/transformations/datacube_mappers/__init__.py +1 -0
  15. polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py +141 -0
  16. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py +5 -0
  17. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py +147 -0
  18. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +229 -0
  19. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +95 -0
  20. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +7896 -0
  21. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_gaussian.py +1459 -0
  22. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +5128 -0
  23. polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py +75 -0
  24. polytope_feature/datacube/transformations/datacube_merger/__init__.py +1 -0
  25. polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py +95 -0
  26. polytope_feature/datacube/transformations/datacube_reverse/__init__.py +1 -0
  27. polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py +65 -0
  28. polytope_feature/datacube/transformations/datacube_transformations.py +96 -0
  29. polytope_feature/datacube/transformations/datacube_type_change/__init__.py +1 -0
  30. polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py +124 -0
  31. polytope_feature/datacube/tree_encoding.py +132 -0
  32. polytope_feature/engine/__init__.py +1 -0
  33. polytope_feature/engine/engine.py +19 -0
  34. polytope_feature/engine/hullslicer.py +316 -0
  35. polytope_feature/options.py +77 -0
  36. polytope_feature/polytope.py +71 -0
  37. polytope_feature/shapes.py +405 -0
  38. polytope_feature/utility/__init__.py +0 -0
  39. polytope_feature/utility/combinatorics.py +48 -0
  40. polytope_feature/utility/exceptions.py +45 -0
  41. polytope_feature/utility/geometry.py +26 -0
  42. polytope_feature/utility/list_tools.py +41 -0
  43. polytope_feature/utility/profiling.py +14 -0
  44. polytope_feature/version.py +1 -0
  45. polytope_python-1.0.31.dist-info/LICENSE +201 -0
  46. polytope_python-1.0.31.dist-info/METADATA +21 -0
  47. polytope_python-1.0.31.dist-info/RECORD +49 -0
  48. polytope_python-1.0.31.dist-info/WHEEL +5 -0
  49. polytope_python-1.0.31.dist-info/top_level.txt +1 -0
@@ -0,0 +1,228 @@
1
+ import logging
2
+ from typing import OrderedDict
3
+
4
+ from sortedcontainers import SortedList
5
+
6
+ from .datacube_axis import IntDatacubeAxis, UnsliceableDatacubeAxis
7
+
8
+
9
+ class DatacubePath(OrderedDict):
10
+ def values(self):
11
+ return tuple(super().values())
12
+
13
+ def keys(self):
14
+ return tuple(super().keys())
15
+
16
+ def pprint(self):
17
+ result = ""
18
+ for k, v in self.items():
19
+ result += f"{k}={v},"
20
+ print(result[:-1])
21
+
22
+
23
+ class TensorIndexTree(object):
24
+ root = IntDatacubeAxis()
25
+ root.name = "root"
26
+
27
+ def __init__(self, axis=root, values=tuple()):
28
+ # NOTE: the values here is a tuple so we can hash it
29
+ self.values = values
30
+ self.children = SortedList()
31
+ self._parent = None
32
+ self.result = []
33
+ self.axis = axis
34
+ self.ancestors = []
35
+ self.indexes = []
36
+ self.hidden = False
37
+
38
+ @property
39
+ def leaves(self):
40
+ leaves = []
41
+ self._collect_leaf_nodes(leaves)
42
+ return leaves
43
+
44
+ def _collect_leaf_nodes(self, leaves):
45
+ if len(self.children) == 0:
46
+ leaves.append(self)
47
+ self.ancestors.append(self)
48
+ for n in self.children:
49
+ for ancestor in self.ancestors:
50
+ n.ancestors.append(ancestor)
51
+ if self.axis != TensorIndexTree.root:
52
+ n.ancestors.append(self)
53
+ n._collect_leaf_nodes(leaves)
54
+
55
+ def __setitem__(self, key, value):
56
+ setattr(self, key, value)
57
+
58
+ def __getitem__(self, key):
59
+ return getattr(self, key)
60
+
61
+ def __delitem__(self, key):
62
+ return delattr(self, key)
63
+
64
+ def __hash__(self):
65
+ return hash((self.axis.name, self.values))
66
+
67
+ def __eq__(self, other):
68
+ if not isinstance(other, TensorIndexTree):
69
+ return False
70
+ if self.axis.name != other.axis.name:
71
+ return False
72
+ else:
73
+ if other.values == self.values:
74
+ return True
75
+ else:
76
+ if isinstance(self.axis, UnsliceableDatacubeAxis):
77
+ return False
78
+ else:
79
+ if len(other.values) != len(self.values):
80
+ return False
81
+ for i in range(len(other.values)):
82
+ other_val = other.values[i]
83
+ self_val = self.values[i]
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
90
+ return True
91
+
92
+ def __lt__(self, other):
93
+ return (self.axis.name, self.values) < (other.axis.name, other.values)
94
+
95
+ def __repr__(self):
96
+ if self.axis != "root":
97
+ return f"{self.axis.name}={self.values}"
98
+ else:
99
+ return f"{self.axis}"
100
+
101
+ def add_child(self, node):
102
+ self.children.add(node)
103
+ node._parent = self
104
+
105
+ def add_value(self, value):
106
+ new_values = list(self.values)
107
+ new_values.append(value)
108
+ new_values.sort()
109
+ self.values = tuple(new_values)
110
+
111
+ def create_child(self, axis, value, next_nodes):
112
+ node = TensorIndexTree(axis, (value,))
113
+ existing_child = self.find_child(node)
114
+ if not existing_child:
115
+ self.add_child(node)
116
+ return (node, next_nodes)
117
+ return (existing_child, next_nodes)
118
+
119
+ @property
120
+ def parent(self):
121
+ return self._parent
122
+
123
+ @parent.setter
124
+ def set_parent(self, node):
125
+ if self.parent is not None:
126
+ self.parent.children.remove(self)
127
+ self._parent = node
128
+ self._parent.children.add(self)
129
+
130
+ def get_root(self):
131
+ node = self
132
+ while node.parent is not None:
133
+ node = node.parent
134
+ return node
135
+
136
+ def is_root(self):
137
+ return self.parent is None
138
+
139
+ def find_child(self, node):
140
+ index = self.children.bisect_left(node)
141
+ if index >= len(self.children):
142
+ return None
143
+ child = self.children[index]
144
+ if not child == node:
145
+ return None
146
+ return child
147
+
148
+ def add_node_layer_after(self, ax_name, vals):
149
+ ax = IntDatacubeAxis()
150
+ ax.name = ax_name
151
+ interm_node = TensorIndexTree(ax, vals)
152
+ interm_node.children = self.children
153
+ interm_node._parent = self
154
+ self.children = SortedList()
155
+ self.children.add(interm_node)
156
+ return interm_node
157
+
158
+ def delete_non_index_nodes(self, index_vals):
159
+ grandparent = self._parent._parent
160
+ grandparent.indexes.extend(index_vals)
161
+ self.remove_branch()
162
+ return grandparent
163
+
164
+ def hide_non_index_nodes(self, index_vals):
165
+ grandparent = self._parent._parent
166
+ grandparent.indexes.extend(index_vals)
167
+ self.hide_two_levels()
168
+ return grandparent
169
+
170
+ def hide_two_levels(self):
171
+ self.hidden = True
172
+ if self._parent.non_hidden_children() == 0:
173
+ self._parent.hidden = True
174
+
175
+ def non_hidden_children(self):
176
+ non_hidden_child_counter = 0
177
+ for c in self.children:
178
+ if not c.hidden:
179
+ non_hidden_child_counter += 1
180
+ return non_hidden_child_counter
181
+
182
+ def merge(self, other):
183
+ for other_child in other.children:
184
+ my_child = self.find_child(other_child)
185
+ if not my_child:
186
+ self.add_child(other_child)
187
+ else:
188
+ my_child.merge(other_child)
189
+
190
+ def pprint(self, level=0):
191
+ if self.axis.name == "root":
192
+ logging.debug("\n")
193
+ logging.debug("\t" * level + "\u21b3" + str(self))
194
+ for child in self.children:
195
+ if not child.hidden:
196
+ child.pprint(level + 1)
197
+ if len(self.children) == 0:
198
+ logging.debug("\t" * (level + 1) + "\u21b3" + str(self.result))
199
+
200
+ def remove_branch(self):
201
+ if not self.is_root():
202
+ old_parent = self._parent
203
+ self._parent.children.remove(self)
204
+ self._parent = None
205
+ if len(old_parent.children) == 0:
206
+ old_parent.remove_branch()
207
+
208
+ def remove_compressed_branch(self, value):
209
+ if value in self.values:
210
+ if len(self.values) == 1:
211
+ self.remove_branch()
212
+ else:
213
+ self.values = tuple(val for val in self.values if val != value)
214
+
215
+ def flatten(self):
216
+ path = DatacubePath()
217
+ ancestors = self.get_ancestors()
218
+ for ancestor in ancestors:
219
+ path[ancestor.axis.name] = ancestor.values
220
+ return path
221
+
222
+ def get_ancestors(self):
223
+ ancestors = []
224
+ current_node = self
225
+ while current_node.axis.name != "root":
226
+ ancestors.append(current_node)
227
+ current_node = current_node.parent
228
+ return ancestors[::-1]
@@ -0,0 +1 @@
1
+ from ..transformations.datacube_transformations import *
@@ -0,0 +1 @@
1
+ from .datacube_cyclic import *
@@ -0,0 +1,171 @@
1
+ import math
2
+ from copy import deepcopy
3
+
4
+ from ....utility.list_tools import unique
5
+ from ..datacube_transformations import DatacubeAxisTransformation
6
+
7
+
8
+ class DatacubeAxisCyclic(DatacubeAxisTransformation):
9
+ # The transformation here will be to point the old axes to the new cyclic axes
10
+
11
+ def __init__(self, name, cyclic_options, datacube=None):
12
+ self.name = name
13
+ self.transformation_options = cyclic_options
14
+ self.range = cyclic_options.range
15
+
16
+ def generate_final_transformation(self):
17
+ return self
18
+
19
+ def transformation_axes_final(self):
20
+ return [self.name]
21
+
22
+ def change_val_type(self, axis_name, values):
23
+ return values
24
+
25
+ def blocked_axes(self):
26
+ return []
27
+
28
+ def unwanted_axes(self):
29
+ return []
30
+
31
+ def update_range(self, axis):
32
+ axis.range = self.range
33
+
34
+ def _remap_range_to_axis_range(self, range, axis):
35
+ self.update_range(axis)
36
+ axis_lower = axis.range[0]
37
+ axis_upper = axis.range[1]
38
+ axis_range = axis_upper - axis_lower
39
+ lower = range[0]
40
+ upper = range[1]
41
+ if lower < axis_lower:
42
+ # In this case we need to calculate the number of loops between the axis lower
43
+ # and the lower to recenter the lower
44
+ loops = int((axis_lower - lower - axis.tol) / axis_range)
45
+ return_lower = lower + (loops + 1) * axis_range
46
+ return_upper = upper + (loops + 1) * axis_range
47
+ elif lower >= axis_upper:
48
+ # In this case we need to calculate the number of loops between the axis upper
49
+ # and the lower to recenter the lower
50
+ loops = int((lower - axis_upper) / axis_range)
51
+ return_lower = lower - (loops + 1) * axis_range
52
+ return_upper = upper - (loops + 1) * axis_range
53
+ else:
54
+ # In this case, the lower value is already in the right range
55
+ return_lower = lower
56
+ return_upper = upper
57
+ return [return_lower, return_upper]
58
+
59
+ def _remap_val_to_axis_range(self, value, axis):
60
+ value = self._remap_range_to_axis_range([value, value], axis)
61
+ return value[0]
62
+
63
+ def offset(self, range, axis, offset):
64
+ # We first unpad the range by the axis tolerance to make sure that
65
+ # we find the wanted range of the cyclic axis since we padded by the axis tolerance before.
66
+ # Also, it's safer that we find the offset of a value inside the range instead of on the border
67
+ unpadded_range = [range[0] + 1.5 * axis.tol, range[1] - 1.5 * axis.tol]
68
+ cyclic_range = self._remap_range_to_axis_range(unpadded_range, axis)
69
+ offset = unpadded_range[0] - cyclic_range[0]
70
+ return offset
71
+
72
+ def remap(self, range, ranges, axis):
73
+ self.update_range(axis)
74
+ if axis.range[0] - axis.tol <= range[0] <= axis.range[1] + axis.tol:
75
+ if axis.range[0] - axis.tol <= range[1] <= axis.range[1] + axis.tol:
76
+ # If we are already in the cyclic range, return it
77
+ return [range]
78
+ elif abs(range[0] - range[1]) <= 2 * axis.tol:
79
+ # If we have a range that is just one point, then it should still be counted
80
+ # and so we should take a small interval around it to find values inbetween
81
+ range = [
82
+ self._remap_val_to_axis_range(range[0], axis) - axis.tol,
83
+ self._remap_val_to_axis_range(range[0], axis) + axis.tol,
84
+ ]
85
+ return [range]
86
+ range_intervals = self.to_intervals(range, [[]], axis)
87
+ ranges = []
88
+ for interval in range_intervals:
89
+ if abs(interval[0] - interval[1]) > 0:
90
+ # If the interval is not just a single point, we remap it to the axis range
91
+ range = self._remap_range_to_axis_range([interval[0], interval[1]], axis)
92
+ up = range[1]
93
+ low = range[0]
94
+ if up < low:
95
+ # Make sure we remap in the right order
96
+ ranges.append([up - axis.tol, low + axis.tol])
97
+ else:
98
+ ranges.append([low - axis.tol, up + axis.tol])
99
+ return ranges
100
+
101
+ def to_intervals(self, range, intervals, axis):
102
+ self.update_range(axis)
103
+ if range[0] == -math.inf:
104
+ range[0] = axis.range[0]
105
+ if range[1] == math.inf:
106
+ range[1] = axis.range[1]
107
+ axis_lower = axis.range[0]
108
+ axis_upper = axis.range[1]
109
+ axis_range = axis_upper - axis_lower
110
+ lower = range[0]
111
+ upper = range[1]
112
+ intervals = []
113
+ if lower < axis_upper:
114
+ # In this case, we want to go from lower to the first remapped cyclic axis upper
115
+ # or the asked upper range value.
116
+ # For example, if we have cyclic range [0,360] and we want to break [-270,180] into intervals,
117
+ # we first want to obtain [-270, 0] as the first range, where 0 is the remapped cyclic axis upper
118
+ # but if we wanted to break [-270, -180] into intervals, we would want to get [-270,-180],
119
+ # where -180 is the asked upper range value.
120
+ loops = int((axis_upper - lower) / axis_range)
121
+ remapped_up = axis_upper - (loops) * axis_range
122
+ new_upper = min(upper, remapped_up)
123
+ else:
124
+ # In this case, since lower >= axis_upper, we need to either go to the asked upper range
125
+ # or we need to go to the first remapped cyclic axis upper which is higher than lower
126
+ new_upper = min(axis_upper + axis_range, upper)
127
+ while new_upper < lower:
128
+ new_upper = min(new_upper + axis_range, upper)
129
+ intervals.append([lower, new_upper])
130
+ # Now that we have established what the first interval should be, we should just jump from cyclic range
131
+ # to cyclic range until we hit the asked upper range value.
132
+ new_up = deepcopy(new_upper)
133
+ while new_up < upper:
134
+ new_upper = new_up
135
+ new_up = min(upper, new_upper + axis_range)
136
+ intervals.append([new_upper, new_up])
137
+ # Once we have added all the in-between ranges, we need to add the last interval
138
+ intervals.append([new_up, upper])
139
+ return intervals
140
+
141
+ def find_indices_between(self, indexes_ranges, low, up, datacube, method, indexes_between_ranges, axis):
142
+ search_ranges = self.remap([low, up], [], axis)
143
+ original_search_ranges = self.to_intervals([low, up], [], axis)
144
+ # Find the offsets for each interval in the requested range, which we will need later
145
+ search_ranges_offset = []
146
+ for r in original_search_ranges:
147
+ offset = self.offset(r, axis, 0)
148
+ search_ranges_offset.append(offset)
149
+ idx_between = []
150
+ for i in range(len(search_ranges)):
151
+ r = search_ranges[i]
152
+ offset = search_ranges_offset[i]
153
+ low = r[0]
154
+ up = r[1]
155
+ indexes_between = axis.find_standard_indices_between(indexes_ranges, low, up, datacube, method)
156
+ # Now the indexes_between are values on the cyclic range so need to remap them to their original
157
+ # values before returning them
158
+ # if we have a special indexes between range that needs additional offset, treat it here
159
+ if len(indexes_between) == 0:
160
+ idx_between = idx_between
161
+ else:
162
+ for k in range(len(indexes_between)):
163
+ if offset is None:
164
+ indexes_between[k] = indexes_between[k]
165
+ else:
166
+ indexes_between[k] = round(indexes_between[k] + offset, int(-math.log10(axis.tol)))
167
+ idx_between.append(indexes_between[k])
168
+ if offset is not None:
169
+ # Note that we can only do unique if not dealing with time values
170
+ idx_between = unique(idx_between)
171
+ return idx_between
@@ -0,0 +1 @@
1
+ from .datacube_mappers import *
@@ -0,0 +1,141 @@
1
+ from copy import deepcopy
2
+ from importlib import import_module
3
+
4
+ from ..datacube_transformations import DatacubeAxisTransformation
5
+
6
+
7
+ class DatacubeMapper(DatacubeAxisTransformation):
8
+ # Needs to implements DatacubeAxisTransformation methods
9
+
10
+ def __init__(self, name, mapper_options, datacube=None):
11
+ self.transformation_options = mapper_options
12
+ self.grid_type = mapper_options.type
13
+ self.grid_resolution = mapper_options.resolution
14
+ self.grid_axes = mapper_options.axes
15
+ self.local_area = []
16
+ self.md5_hash = None
17
+ if mapper_options.md5_hash is not None:
18
+ self.md5_hash = mapper_options.md5_hash
19
+ if mapper_options.local is not None:
20
+ self.local_area = mapper_options.local
21
+ self._axis_reversed = None
22
+ if mapper_options.axis_reversed is not None:
23
+ self._axis_reversed = mapper_options.axis_reversed
24
+ self.old_axis = name
25
+ self._final_transformation = self.generate_final_transformation()
26
+ self._final_mapped_axes = self._final_transformation._mapped_axes
27
+ self._axis_reversed = self._final_transformation._axis_reversed
28
+ self.compressed_grid_axes = self._final_transformation.compressed_grid_axes
29
+ self.md5_hash = self._final_transformation.md5_hash
30
+
31
+ def generate_final_transformation(self):
32
+ map_type = _type_to_datacube_mapper_lookup[self.grid_type]
33
+ module = import_module(
34
+ "polytope_feature.datacube.transformations.datacube_mappers.mapper_types." + self.grid_type
35
+ )
36
+ constructor = getattr(module, map_type)
37
+ transformation = deepcopy(
38
+ constructor(
39
+ self.old_axis, self.grid_axes, self.grid_resolution, self.md5_hash, self.local_area, self._axis_reversed
40
+ )
41
+ )
42
+ return transformation
43
+
44
+ def blocked_axes(self):
45
+ return []
46
+
47
+ def unwanted_axes(self):
48
+ return [self._final_mapped_axes[0]]
49
+
50
+ def transformation_axes_final(self):
51
+ final_axes = self._final_mapped_axes
52
+ return final_axes
53
+
54
+ # Needs to also implement its own methods
55
+
56
+ def change_val_type(self, axis_name, values):
57
+ # the new axis_vals created will be floats
58
+ return [0.0]
59
+
60
+ def _mapped_axes(self):
61
+ # NOTE: Each of the mapper method needs to call it's sub mapper method
62
+ final_axes = self._final_mapped_axes
63
+ return final_axes
64
+
65
+ def _base_axis(self):
66
+ pass
67
+
68
+ def _resolution(self):
69
+ pass
70
+
71
+ def first_axis_vals(self):
72
+ return self._final_transformation.first_axis_vals()
73
+
74
+ def second_axis_vals(self, first_val):
75
+ return self._final_transformation.second_axis_vals(first_val)
76
+
77
+ def map_first_axis(self, lower, upper):
78
+ return self._final_transformation.map_first_axis(lower, upper)
79
+
80
+ def map_second_axis(self, first_val, lower, upper):
81
+ return self._final_transformation.map_second_axis(first_val, lower, upper)
82
+
83
+ def find_second_idx(self, first_val, second_val):
84
+ return self._final_transformation.find_second_idx(first_val, second_val)
85
+
86
+ def unmap_first_val_to_start_line_idx(self, first_val):
87
+ return self._final_transformation.unmap_first_val_to_start_line_idx(first_val)
88
+
89
+ def unmap(self, first_val, second_val):
90
+ return self._final_transformation.unmap(first_val, second_val)
91
+
92
+ def find_modified_indexes(self, indexes, path, datacube, axis):
93
+ if axis.name == self._mapped_axes()[0]:
94
+ return self.first_axis_vals()
95
+ if axis.name == self._mapped_axes()[1]:
96
+ first_val = path[self._mapped_axes()[0]]
97
+ if not isinstance(first_val, tuple):
98
+ first_val = (first_val,)
99
+ return self.second_axis_vals(first_val)
100
+
101
+ def unmap_path_key(self, key_value_path, leaf_path, unwanted_path, axis):
102
+ value = key_value_path[axis.name]
103
+ if axis.name == self._mapped_axes()[0]:
104
+ unwanted_val = key_value_path[self._mapped_axes()[0]]
105
+ unwanted_path[axis.name] = unwanted_val
106
+ if axis.name == self._mapped_axes()[1]:
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)
112
+ leaf_path.pop(self._mapped_axes()[0], None)
113
+ key_value_path.pop(axis.name)
114
+ key_value_path[self.old_axis] = unmapped_idx
115
+ return (key_value_path, leaf_path, unwanted_path)
116
+
117
+ def unmap_tree_node(self, node, unwanted_path):
118
+ values = node.values
119
+ if node.axis.name == self._mapped_axes()[0]:
120
+ unwanted_path[node.axis.name] = values
121
+ returned_node = node
122
+ if node.axis.name == self._mapped_axes()[1]:
123
+ first_vals = unwanted_path[self._mapped_axes()[0]]
124
+ unmapped_idxs = []
125
+ for first_val in first_vals:
126
+ for val in values:
127
+ unmapped_idx = self.unmap([first_val], [val])
128
+ unmapped_idxs.append(unmapped_idx)
129
+ returned_node = node.hide_non_index_nodes(unmapped_idxs)
130
+ return (returned_node, unwanted_path)
131
+
132
+
133
+ _type_to_datacube_mapper_lookup = {
134
+ "octahedral": "OctahedralGridMapper",
135
+ "healpix": "HealpixGridMapper",
136
+ "regular": "RegularGridMapper",
137
+ "reduced_ll": "ReducedLatLonMapper",
138
+ "local_regular": "LocalRegularGridMapper",
139
+ "healpix_nested": "NestedHealpixGridMapper",
140
+ "reduced_gaussian": "ReducedGaussianGridMapper",
141
+ }
@@ -0,0 +1,5 @@
1
+ from .healpix import *
2
+ from .local_regular import *
3
+ from .octahedral import *
4
+ from .reduced_ll import *
5
+ from .regular import *