polytope-python 1.0.6__tar.gz → 1.0.7__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.
- {polytope-python-1.0.6/polytope_python.egg-info → polytope-python-1.0.7}/PKG-INFO +1 -1
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/backends/datacube.py +5 -3
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/backends/fdb.py +8 -10
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/backends/mock.py +3 -1
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/backends/xarray.py +5 -3
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/tensor_index_tree.py +1 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/datacube_mappers.py +1 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix.py +5 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +5 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +6 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +7 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +5 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/regular.py +5 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_merger/datacube_merger.py +0 -1
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/engine/hullslicer.py +18 -32
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/options.py +0 -1
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/polytope.py +8 -2
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/exceptions.py +8 -4
- polytope-python-1.0.7/polytope/version.py +1 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7/polytope_python.egg-info}/PKG-INFO +1 -1
- polytope-python-1.0.6/polytope/version.py +0 -1
- {polytope-python-1.0.6 → polytope-python-1.0.7}/LICENSE +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/MANIFEST.in +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/backends/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/datacube_axis.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/index_tree_pb2.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_cyclic/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_merger/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_reverse/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_transformations.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_type_change/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/datacube_type_change/datacube_type_change.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/tree_encoding.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/engine/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/engine/engine.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/shapes.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/__init__.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/combinatorics.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/geometry.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/list_tools.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/utility/profiling.py +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/SOURCES.txt +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/dependency_links.txt +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/not-zip-safe +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/requires.txt +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/top_level.txt +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/pyproject.toml +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/requirements.txt +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/setup.cfg +0 -0
- {polytope-python-1.0.6 → polytope-python-1.0.7}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ...utility.combinatorics import validate_axes
|
|
6
6
|
from ..datacube_axis import DatacubeAxis
|
|
@@ -31,9 +31,10 @@ class Datacube(ABC):
|
|
|
31
31
|
self.merged_axes = []
|
|
32
32
|
self.unwanted_path = {}
|
|
33
33
|
self.compressed_axes = compressed_axes_options
|
|
34
|
+
self.grid_md5_hash = None
|
|
34
35
|
|
|
35
36
|
@abstractmethod
|
|
36
|
-
def get(self, requests: TensorIndexTree) -> Any:
|
|
37
|
+
def get(self, requests: TensorIndexTree, context: Dict) -> Any:
|
|
37
38
|
"""Return data given a set of request trees"""
|
|
38
39
|
|
|
39
40
|
@property
|
|
@@ -69,6 +70,7 @@ class Datacube(ABC):
|
|
|
69
70
|
# TODO: do we use this?? This shouldn't work for a disk in lat/lon on a octahedral or other grid??
|
|
70
71
|
for compressed_grid_axis in transformation.compressed_grid_axes:
|
|
71
72
|
self.compressed_grid_axes.append(compressed_grid_axis)
|
|
73
|
+
self.grid_md5_hash = transformation.md5_hash
|
|
72
74
|
if len(final_axis_names) > 1:
|
|
73
75
|
self.coupled_axes.append(final_axis_names)
|
|
74
76
|
for axis in final_axis_names:
|
|
@@ -128,7 +130,7 @@ class Datacube(ABC):
|
|
|
128
130
|
indexes = axis.find_indexes(path, self)
|
|
129
131
|
idx_between = axis.find_indices_between(indexes, lower, upper, self, method)
|
|
130
132
|
|
|
131
|
-
logging.
|
|
133
|
+
logging.debug(f"For axis {axis.name} between {lower} and {upper}, found indices {idx_between}")
|
|
132
134
|
|
|
133
135
|
return idx_between
|
|
134
136
|
|
|
@@ -77,7 +77,9 @@ class FDBDatacube(Datacube):
|
|
|
77
77
|
for axis_name in axes_to_remove:
|
|
78
78
|
self._axes.pop(axis_name, None)
|
|
79
79
|
|
|
80
|
-
def get(self, requests: TensorIndexTree):
|
|
80
|
+
def get(self, requests: TensorIndexTree, context=None):
|
|
81
|
+
if context is None:
|
|
82
|
+
context = {}
|
|
81
83
|
requests.pprint()
|
|
82
84
|
if len(requests.children) == 0:
|
|
83
85
|
return requests
|
|
@@ -104,11 +106,11 @@ class FDBDatacube(Datacube):
|
|
|
104
106
|
uncompressed_request = {}
|
|
105
107
|
for i, key in enumerate(compressed_request[0].keys()):
|
|
106
108
|
uncompressed_request[key] = combi[i]
|
|
107
|
-
complete_uncompressed_request = (uncompressed_request, compressed_request[1])
|
|
109
|
+
complete_uncompressed_request = (uncompressed_request, compressed_request[1], self.grid_md5_hash)
|
|
108
110
|
complete_list_complete_uncompressed_requests.append(complete_uncompressed_request)
|
|
109
111
|
complete_fdb_decoding_info.append(fdb_requests_decoding_info[j])
|
|
110
112
|
logging.debug("The requests we give GribJump are: %s", complete_list_complete_uncompressed_requests)
|
|
111
|
-
output_values = self.gj.extract(complete_list_complete_uncompressed_requests)
|
|
113
|
+
output_values = self.gj.extract(complete_list_complete_uncompressed_requests, context)
|
|
112
114
|
logging.debug("GribJump outputs: %s", output_values)
|
|
113
115
|
self.assign_fdb_output_to_nodes(output_values, complete_fdb_decoding_info)
|
|
114
116
|
|
|
@@ -124,7 +126,7 @@ class FDBDatacube(Datacube):
|
|
|
124
126
|
|
|
125
127
|
# First when request node is root, go to its children
|
|
126
128
|
if requests.axis.name == "root":
|
|
127
|
-
logging.
|
|
129
|
+
logging.debug("Looking for data for the tree: %s", [leaf.flatten() for leaf in requests.leaves])
|
|
128
130
|
|
|
129
131
|
for c in requests.children:
|
|
130
132
|
self.get_fdb_requests(c, fdb_requests, fdb_requests_decoding_info)
|
|
@@ -161,8 +163,8 @@ class FDBDatacube(Datacube):
|
|
|
161
163
|
new_current_start_idx = []
|
|
162
164
|
for j, idx in enumerate(sub_lat_idxs):
|
|
163
165
|
if idx not in seen_indices:
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
+
# NOTE: need to remove it from the values in the corresponding tree node
|
|
167
|
+
# NOTE: need to read just the range we give to gj
|
|
166
168
|
original_fdb_node_range_vals.append(actual_fdb_node[0].values[j])
|
|
167
169
|
seen_indices.add(idx)
|
|
168
170
|
new_current_start_idx.append(idx)
|
|
@@ -187,8 +189,6 @@ class FDBDatacube(Datacube):
|
|
|
187
189
|
|
|
188
190
|
second_ax = requests.children[0].children[0].axis
|
|
189
191
|
|
|
190
|
-
# TODO: actually, here we should not remap the nearest_pts, we should instead unmap the
|
|
191
|
-
# found_latlon_pts and then remap them later once we have compared found_latlon_pts and nearest_pts
|
|
192
192
|
nearest_pts = [
|
|
193
193
|
[lat_val, second_ax._remap_val_to_axis_range(lon_val)]
|
|
194
194
|
for (lat_val, lon_val) in zip(
|
|
@@ -325,8 +325,6 @@ 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)
|
|
330
328
|
return (original_indices, sorted_request_ranges, new_fdb_node_ranges)
|
|
331
329
|
|
|
332
330
|
def datacube_natural_indexes(self, axis, subarray):
|
|
@@ -24,10 +24,12 @@ class MockDatacube(Datacube):
|
|
|
24
24
|
self.stride[k] = stride_cumulative
|
|
25
25
|
stride_cumulative *= self.dimensions[k]
|
|
26
26
|
|
|
27
|
-
def get(self, requests: TensorIndexTree):
|
|
27
|
+
def get(self, requests: TensorIndexTree, context=None):
|
|
28
28
|
# Takes in a datacube and verifies the leaves of the tree are complete
|
|
29
29
|
# (ie it found values for all datacube axis)
|
|
30
30
|
|
|
31
|
+
if context is None:
|
|
32
|
+
context = {}
|
|
31
33
|
for r in requests.leaves:
|
|
32
34
|
path = r.flatten()
|
|
33
35
|
if len(path.items()) == len(self.dimensions.items()):
|
|
@@ -50,12 +50,14 @@ class XArrayDatacube(Datacube):
|
|
|
50
50
|
val = self._axes[name].type
|
|
51
51
|
self._check_and_add_axes(options, name, val)
|
|
52
52
|
|
|
53
|
-
def get(self, requests, leaf_path=None, axis_counter=0):
|
|
53
|
+
def get(self, requests, context=None, leaf_path=None, axis_counter=0):
|
|
54
|
+
if context is None:
|
|
55
|
+
context = {}
|
|
54
56
|
if leaf_path is None:
|
|
55
57
|
leaf_path = {}
|
|
56
58
|
if requests.axis.name == "root":
|
|
57
59
|
for c in requests.children:
|
|
58
|
-
self.get(c, leaf_path, axis_counter + 1)
|
|
60
|
+
self.get(c, context, leaf_path, axis_counter + 1)
|
|
59
61
|
else:
|
|
60
62
|
key_value_path = {requests.axis.name: requests.values}
|
|
61
63
|
ax = requests.axis
|
|
@@ -66,7 +68,7 @@ class XArrayDatacube(Datacube):
|
|
|
66
68
|
if len(requests.children) != 0:
|
|
67
69
|
# We are not a leaf and we loop over
|
|
68
70
|
for c in requests.children:
|
|
69
|
-
self.get(c, leaf_path, axis_counter + 1)
|
|
71
|
+
self.get(c, context, leaf_path, axis_counter + 1)
|
|
70
72
|
else:
|
|
71
73
|
if self.axis_counter != axis_counter:
|
|
72
74
|
requests.remove_branch()
|
|
@@ -20,6 +20,7 @@ class DatacubeMapper(DatacubeAxisTransformation):
|
|
|
20
20
|
self._final_mapped_axes = self._final_transformation._mapped_axes
|
|
21
21
|
self._axis_reversed = self._final_transformation._axis_reversed
|
|
22
22
|
self.compressed_grid_axes = self._final_transformation.compressed_grid_axes
|
|
23
|
+
self.md5_hash = self._final_transformation.md5_hash
|
|
23
24
|
|
|
24
25
|
def generate_final_transformation(self):
|
|
25
26
|
map_type = _type_to_datacube_mapper_lookup[self.grid_type]
|
|
@@ -13,6 +13,7 @@ class HealpixGridMapper(DatacubeMapper):
|
|
|
13
13
|
self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False}
|
|
14
14
|
self._first_axis_vals = self.first_axis_vals()
|
|
15
15
|
self.compressed_grid_axes = [self._mapped_axes[1]]
|
|
16
|
+
self.md5_hash = md5_hash.get(resolution, None)
|
|
16
17
|
|
|
17
18
|
def first_axis_vals(self):
|
|
18
19
|
rad2deg = 180 / math.pi
|
|
@@ -133,3 +134,7 @@ class HealpixGridMapper(DatacubeMapper):
|
|
|
133
134
|
second_idx = self.second_axis_vals(first_val).index(second_val)
|
|
134
135
|
healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx)
|
|
135
136
|
return healpix_index
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# md5 grid hash in form {resolution : hash}
|
|
140
|
+
md5_hash = {}
|
|
@@ -17,6 +17,7 @@ class NestedHealpixGridMapper(DatacubeMapper):
|
|
|
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.md5_hash = md5_hash.get(resolution, None)
|
|
20
21
|
|
|
21
22
|
def first_axis_vals(self):
|
|
22
23
|
rad2deg = 180 / math.pi
|
|
@@ -211,3 +212,7 @@ class NestedHealpixGridMapper(DatacubeMapper):
|
|
|
211
212
|
|
|
212
213
|
def int_sqrt(self, i):
|
|
213
214
|
return int(math.sqrt(i + 0.5))
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# md5 grid hash in form {resolution : hash}
|
|
218
|
+
md5_hash = {}
|
|
@@ -15,9 +15,11 @@ class LocalRegularGridMapper(DatacubeMapper):
|
|
|
15
15
|
if not isinstance(resolution, list):
|
|
16
16
|
self.first_resolution = resolution
|
|
17
17
|
self.second_resolution = resolution
|
|
18
|
+
self.md5_hash = md5_hash.get(resolution, None)
|
|
18
19
|
else:
|
|
19
20
|
self.first_resolution = resolution[0]
|
|
20
21
|
self.second_resolution = resolution[1]
|
|
22
|
+
self.md5_hash = md5_hash.get(tuple(resolution), None)
|
|
21
23
|
self._first_deg_increment = (local_area[1] - local_area[0]) / self.first_resolution
|
|
22
24
|
self._second_deg_increment = (local_area[3] - local_area[2]) / self.second_resolution
|
|
23
25
|
self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False}
|
|
@@ -68,3 +70,7 @@ class LocalRegularGridMapper(DatacubeMapper):
|
|
|
68
70
|
second_idx = self.second_axis_vals(first_val).index(second_val)
|
|
69
71
|
final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
|
|
70
72
|
return final_index
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# md5 grid hash in form {resolution : hash}
|
|
76
|
+
md5_hash = {}
|
|
@@ -15,6 +15,7 @@ class OctahedralGridMapper(DatacubeMapper):
|
|
|
15
15
|
self._second_axis_spacing = {}
|
|
16
16
|
self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False}
|
|
17
17
|
self.compressed_grid_axes = [self._mapped_axes[1]]
|
|
18
|
+
self.md5_hash = md5_hash.get(resolution, None)
|
|
18
19
|
|
|
19
20
|
def gauss_first_guess(self):
|
|
20
21
|
i = 0
|
|
@@ -2750,3 +2751,9 @@ class OctahedralGridMapper(DatacubeMapper):
|
|
|
2750
2751
|
(first_idx, second_idx) = self.find_second_axis_idx(first_val, second_val)
|
|
2751
2752
|
octahedral_index = self.axes_idx_to_octahedral_idx(first_idx, second_idx)
|
|
2752
2753
|
return octahedral_index
|
|
2754
|
+
|
|
2755
|
+
|
|
2756
|
+
# md5 grid hash in form {resolution : hash}
|
|
2757
|
+
md5_hash = {
|
|
2758
|
+
1280: "158db321ae8e773681eeb40e0a3d350f",
|
|
2759
|
+
}
|
|
@@ -12,6 +12,7 @@ class ReducedLatLonMapper(DatacubeMapper):
|
|
|
12
12
|
self._axis_reversed = {mapped_axes[0]: False, mapped_axes[1]: False}
|
|
13
13
|
self._first_axis_vals = self.first_axis_vals()
|
|
14
14
|
self.compressed_grid_axes = [self._mapped_axes[1]]
|
|
15
|
+
self.md5_hash = md5_hash.get(resolution, None)
|
|
15
16
|
|
|
16
17
|
def first_axis_vals(self):
|
|
17
18
|
resolution = 180 / (self._resolution - 1)
|
|
@@ -1504,3 +1505,7 @@ class ReducedLatLonMapper(DatacubeMapper):
|
|
|
1504
1505
|
second_idx = self.second_axis_vals(first_val).index(second_val)
|
|
1505
1506
|
reduced_ll_index = self.axes_idx_to_reduced_ll_idx(first_idx, second_idx)
|
|
1506
1507
|
return reduced_ll_index
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
# md5 grid hash in form {resolution : hash}
|
|
1511
|
+
md5_hash = {}
|
|
@@ -13,6 +13,7 @@ class RegularGridMapper(DatacubeMapper):
|
|
|
13
13
|
self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False}
|
|
14
14
|
self._first_axis_vals = self.first_axis_vals()
|
|
15
15
|
self.compressed_grid_axes = [self._mapped_axes[1]]
|
|
16
|
+
self.md5_hash = md5_hash.get(resolution, None)
|
|
16
17
|
|
|
17
18
|
def first_axis_vals(self):
|
|
18
19
|
first_ax_vals = [90 - i * self.deg_increment for i in range(2 * self._resolution)]
|
|
@@ -56,3 +57,7 @@ class RegularGridMapper(DatacubeMapper):
|
|
|
56
57
|
second_idx = self.second_axis_vals(first_val).index(second_val)
|
|
57
58
|
final_index = self.axes_idx_to_regular_idx(first_idx, second_idx)
|
|
58
59
|
return final_index
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# md5 grid hash in form {resolution : hash}
|
|
63
|
+
md5_hash = {}
|
|
@@ -93,6 +93,5 @@ class DatacubeAxisMerger(DatacubeAxisTransformation):
|
|
|
93
93
|
if node.axis.name == self._first_axis:
|
|
94
94
|
(new_first_vals, new_second_vals) = self.unmerge(node.values)
|
|
95
95
|
node.values = new_first_vals
|
|
96
|
-
# TODO: actually need to give the second axis of the transformation to get the interm axis
|
|
97
96
|
interm_node = node.add_node_layer_after(self._second_axis, new_second_vals)
|
|
98
97
|
return (interm_node, unwanted_path)
|
|
@@ -110,7 +110,7 @@ class HullSlicer(Engine):
|
|
|
110
110
|
|
|
111
111
|
def _build_sliceable_child(self, polytope, ax, node, datacube, values, next_nodes, slice_axis_idx):
|
|
112
112
|
for i, value in enumerate(values):
|
|
113
|
-
if i == 0:
|
|
113
|
+
if i == 0 or ax.name not in self.compressed_axes:
|
|
114
114
|
fvalue = ax.to_float(value)
|
|
115
115
|
new_polytope = slice(polytope, ax.name, fvalue, slice_axis_idx)
|
|
116
116
|
remapped_val = self.remap_values(ax, value)
|
|
@@ -121,19 +121,8 @@ class HullSlicer(Engine):
|
|
|
121
121
|
child["unsliced_polytopes"].add(new_polytope)
|
|
122
122
|
next_nodes.append(child)
|
|
123
123
|
else:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
new_polytope = slice(polytope, ax.name, fvalue, slice_axis_idx)
|
|
127
|
-
remapped_val = self.remap_values(ax, value)
|
|
128
|
-
(child, next_nodes) = node.create_child(ax, remapped_val, next_nodes)
|
|
129
|
-
child["unsliced_polytopes"] = copy(node["unsliced_polytopes"])
|
|
130
|
-
child["unsliced_polytopes"].remove(polytope)
|
|
131
|
-
if new_polytope is not None:
|
|
132
|
-
child["unsliced_polytopes"].add(new_polytope)
|
|
133
|
-
next_nodes.append(child)
|
|
134
|
-
else:
|
|
135
|
-
remapped_val = self.remap_values(ax, value)
|
|
136
|
-
child.add_value(remapped_val)
|
|
124
|
+
remapped_val = self.remap_values(ax, value)
|
|
125
|
+
child.add_value(remapped_val)
|
|
137
126
|
|
|
138
127
|
def _build_branch(self, ax, node, datacube, next_nodes):
|
|
139
128
|
if ax.name not in self.compressed_axes:
|
|
@@ -142,26 +131,23 @@ class HullSlicer(Engine):
|
|
|
142
131
|
for polytope in node["unsliced_polytopes"]:
|
|
143
132
|
if ax.name in polytope._axes:
|
|
144
133
|
right_unsliced_polytopes.append(polytope)
|
|
145
|
-
# for polytope in node["unsliced_polytopes"]:
|
|
146
134
|
for i, polytope in enumerate(right_unsliced_polytopes):
|
|
147
135
|
node._parent = parent_node
|
|
148
|
-
|
|
149
|
-
if
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
# we
|
|
160
|
-
if
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
node.remove_branch()
|
|
164
|
-
self._build_sliceable_child(polytope, ax, node, datacube, values, next_nodes, slice_axis_idx)
|
|
136
|
+
lower, upper, slice_axis_idx = polytope.extents(ax.name)
|
|
137
|
+
# here, first check if the axis is an unsliceable axis and directly build node if it is
|
|
138
|
+
# NOTE: we should have already created the ax_is_unsliceable cache before
|
|
139
|
+
if self.ax_is_unsliceable[ax.name]:
|
|
140
|
+
self._build_unsliceable_child(polytope, ax, node, datacube, [lower], next_nodes, slice_axis_idx)
|
|
141
|
+
else:
|
|
142
|
+
values = self.find_values_between(polytope, ax, node, datacube, lower, upper)
|
|
143
|
+
# NOTE: need to only remove the branches if the values are empty,
|
|
144
|
+
# but only if there are no other possible children left in the tree that
|
|
145
|
+
# we can append and if somehow this happens before and we need to remove, then what do we do??
|
|
146
|
+
if i == len(right_unsliced_polytopes) - 1:
|
|
147
|
+
# we have iterated all polytopes and we can now remove the node if we need to
|
|
148
|
+
if len(values) == 0 and len(node.children) == 0:
|
|
149
|
+
node.remove_branch()
|
|
150
|
+
self._build_sliceable_child(polytope, ax, node, datacube, values, next_nodes, slice_axis_idx)
|
|
165
151
|
else:
|
|
166
152
|
all_values = []
|
|
167
153
|
all_lowers = []
|
|
@@ -66,7 +66,6 @@ class Config(ConfigModel):
|
|
|
66
66
|
class PolytopeOptions(ABC):
|
|
67
67
|
@staticmethod
|
|
68
68
|
def get_polytope_options(options):
|
|
69
|
-
|
|
70
69
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
|
71
70
|
conflator = Conflator(app_name="polytope", model=Config, cli=False, argparser=parser, **options)
|
|
72
71
|
config_options = conflator.load()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from typing import List
|
|
2
3
|
|
|
3
4
|
from .options import PolytopeOptions
|
|
@@ -55,9 +56,14 @@ class Polytope:
|
|
|
55
56
|
"""Low-level API which takes a polytope geometry object and uses it to slice the datacube"""
|
|
56
57
|
return self.engine.extract(self.datacube, polytopes)
|
|
57
58
|
|
|
58
|
-
def retrieve(self, request: Request, method="standard"):
|
|
59
|
+
def retrieve(self, request: Request, method="standard", context=None):
|
|
59
60
|
"""Higher-level API which takes a request and uses it to slice the datacube"""
|
|
61
|
+
if context is None:
|
|
62
|
+
context = {}
|
|
63
|
+
logging.info("Starting request for %s ", context)
|
|
60
64
|
self.datacube.check_branching_axes(request)
|
|
61
65
|
request_tree = self.engine.extract(self.datacube, request.polytopes())
|
|
62
|
-
|
|
66
|
+
logging.info("Created request tree for %s ", context)
|
|
67
|
+
self.datacube.get(request_tree, context)
|
|
68
|
+
logging.info("Retrieved data for %s ", context)
|
|
63
69
|
return request_tree
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
class
|
|
1
|
+
class PolytopeError(Exception):
|
|
2
|
+
pass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AxisOverdefinedError(PolytopeError, KeyError):
|
|
2
6
|
def __init__(self, axis):
|
|
3
7
|
self.axis = axis
|
|
4
8
|
self.message = (
|
|
@@ -7,19 +11,19 @@ class AxisOverdefinedError(KeyError):
|
|
|
7
11
|
)
|
|
8
12
|
|
|
9
13
|
|
|
10
|
-
class AxisUnderdefinedError(KeyError):
|
|
14
|
+
class AxisUnderdefinedError(PolytopeError, KeyError):
|
|
11
15
|
def __init__(self, axis):
|
|
12
16
|
self.axis = axis
|
|
13
17
|
self.message = f"Axis {axis} is underdefined. It does not appear in any input polytope."
|
|
14
18
|
|
|
15
19
|
|
|
16
|
-
class AxisNotFoundError(KeyError):
|
|
20
|
+
class AxisNotFoundError(PolytopeError, KeyError):
|
|
17
21
|
def __init__(self, axis):
|
|
18
22
|
self.axis = axis
|
|
19
23
|
self.message = f"Axis {axis} does not exist in the datacube."
|
|
20
24
|
|
|
21
25
|
|
|
22
|
-
class UnsliceableShapeError(KeyError):
|
|
26
|
+
class UnsliceableShapeError(PolytopeError, KeyError):
|
|
23
27
|
def __init__(self, axis):
|
|
24
28
|
self.axis = axis
|
|
25
29
|
self.message = f"Higher-dimensional shape does not support unsliceable axis {axis.name}."
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.7"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.0.6"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{polytope-python-1.0.6 → polytope-python-1.0.7}/polytope/datacube/transformations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{polytope-python-1.0.6 → polytope-python-1.0.7}/polytope_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|