diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fb1be91ea..bc914a979 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -135,7 +135,7 @@ jobs: python -m coverage report - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: files: coverage.xml deploy: diff --git a/.gitignore b/.gitignore index 5dbb14f04..54ea62f14 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ polytope_venv polytope_venv_latest new_updated_numpy_venv newest-polytope-venv +serializedTree diff --git a/codecov.yml b/codecov.yml index f75c21feb..f911473e5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,6 @@ +codecov: + branch: develop # set new Default branch + ignore: - "tests" # ignore tests folder - "**/test*" diff --git a/polytope/options.py b/polytope/options.py deleted file mode 100644 index 7cce36b9d..000000000 --- a/polytope/options.py +++ /dev/null @@ -1,67 +0,0 @@ -import argparse -from abc import ABC -from typing import Dict, List, Literal, Optional, Union - -from conflator import ConfigModel, Conflator -from pydantic import ConfigDict - - -class PolytopeOptions(ABC): - @staticmethod - def get_polytope_options(options): - class TransformationConfig(ConfigModel): - model_config = ConfigDict(extra="forbid") - name: str = "" - - class CyclicConfig(TransformationConfig): - name: Literal["cyclic"] - range: List[float] = [0] - - class MapperConfig(TransformationConfig): - name: Literal["mapper"] - type: str = "" - resolution: Union[int, List[int]] = 0 - axes: List[str] = [""] - local: Optional[List[float]] = None - - class ReverseConfig(TransformationConfig): - name: Literal["reverse"] - is_reverse: bool = False - - class TypeChangeConfig(TransformationConfig): - name: Literal["type_change"] - type: str = "int" - - class MergeConfig(TransformationConfig): - name: Literal["merge"] - other_axis: str = "" - linkers: List[str] = [""] - - action_subclasses_union = Union[CyclicConfig, MapperConfig, ReverseConfig, TypeChangeConfig, MergeConfig] - - class AxisConfig(ConfigModel): - axis_name: str = "" - transformations: list[action_subclasses_union] - - path_subclasses_union = Union[str, int, float] - - class GribJumpAxesConfig(ConfigModel): - axis_name: str = "" - values: List[str] = [""] - - class Config(ConfigModel): - axis_config: List[AxisConfig] = [] - compressed_axes_config: List[str] = [""] - pre_path: Optional[Dict[str, path_subclasses_union]] = {} - alternative_axes: List[GribJumpAxesConfig] = [] - - parser = argparse.ArgumentParser(allow_abbrev=False) - conflator = Conflator(app_name="polytope", model=Config, cli=False, argparser=parser, **options) - config_options = conflator.load() - - axis_config = config_options.axis_config - compressed_axes_config = config_options.compressed_axes_config - pre_path = config_options.pre_path - alternative_axes = config_options.alternative_axes - - return (axis_config, compressed_axes_config, pre_path, alternative_axes) diff --git a/polytope/version.py b/polytope/version.py deleted file mode 100644 index 68cdeee4b..000000000 --- a/polytope/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.0.5" diff --git a/polytope/__init__.py b/polytope_feature/__init__.py similarity index 100% rename from polytope/__init__.py rename to polytope_feature/__init__.py diff --git a/polytope/datacube/__init__.py b/polytope_feature/datacube/__init__.py similarity index 100% rename from polytope/datacube/__init__.py rename to polytope_feature/datacube/__init__.py diff --git a/polytope/datacube/backends/__init__.py b/polytope_feature/datacube/backends/__init__.py similarity index 100% rename from polytope/datacube/backends/__init__.py rename to polytope_feature/datacube/backends/__init__.py diff --git a/polytope/datacube/backends/datacube.py b/polytope_feature/datacube/backends/datacube.py similarity index 95% rename from polytope/datacube/backends/datacube.py rename to polytope_feature/datacube/backends/datacube.py index a1dfbfb30..58c186a61 100644 --- a/polytope/datacube/backends/datacube.py +++ b/polytope_feature/datacube/backends/datacube.py @@ -1,6 +1,6 @@ import logging from abc import ABC, abstractmethod -from typing import Any +from typing import Any, Dict from ...utility.combinatorics import validate_axes from ..datacube_axis import DatacubeAxis @@ -31,9 +31,10 @@ def __init__(self, axis_options=None, compressed_axes_options=[]): self.merged_axes = [] self.unwanted_path = {} self.compressed_axes = compressed_axes_options + self.grid_md5_hash = None @abstractmethod - def get(self, requests: TensorIndexTree) -> Any: + def get(self, requests: TensorIndexTree, context: Dict) -> Any: """Return data given a set of request trees""" @property @@ -69,6 +70,7 @@ def _create_axes(self, name, values, transformation_type_key, transformation_opt # TODO: do we use this?? This shouldn't work for a disk in lat/lon on a octahedral or other grid?? for compressed_grid_axis in transformation.compressed_grid_axes: self.compressed_grid_axes.append(compressed_grid_axis) + self.grid_md5_hash = transformation.md5_hash if len(final_axis_names) > 1: self.coupled_axes.append(final_axis_names) for axis in final_axis_names: @@ -126,9 +128,10 @@ def get_indices(self, path: DatacubePath, axis, lower, upper, method=None): """ path = self.fit_path(path) indexes = axis.find_indexes(path, self) + idx_between = axis.find_indices_between(indexes, lower, upper, self, method) - logging.info(f"For axis {axis.name} between {lower} and {upper}, found indices {idx_between}") + logging.debug(f"For axis {axis.name} between {lower} and {upper}, found indices {idx_between}") return idx_between diff --git a/polytope/datacube/backends/fdb.py b/polytope_feature/datacube/backends/fdb.py similarity index 95% rename from polytope/datacube/backends/fdb.py rename to polytope_feature/datacube/backends/fdb.py index fd10a130b..cc427f566 100644 --- a/polytope/datacube/backends/fdb.py +++ b/polytope_feature/datacube/backends/fdb.py @@ -77,7 +77,9 @@ def check_branching_axes(self, request): for axis_name in axes_to_remove: self._axes.pop(axis_name, None) - def get(self, requests: TensorIndexTree): + def get(self, requests: TensorIndexTree, context=None): + if context is None: + context = {} requests.pprint() if len(requests.children) == 0: return requests @@ -104,11 +106,11 @@ def get(self, requests: TensorIndexTree): uncompressed_request = {} for i, key in enumerate(compressed_request[0].keys()): uncompressed_request[key] = combi[i] - complete_uncompressed_request = (uncompressed_request, compressed_request[1]) + complete_uncompressed_request = (uncompressed_request, compressed_request[1], self.grid_md5_hash) complete_list_complete_uncompressed_requests.append(complete_uncompressed_request) complete_fdb_decoding_info.append(fdb_requests_decoding_info[j]) logging.debug("The requests we give GribJump are: %s", complete_list_complete_uncompressed_requests) - output_values = self.gj.extract(complete_list_complete_uncompressed_requests) + output_values = self.gj.extract(complete_list_complete_uncompressed_requests, context) logging.debug("GribJump outputs: %s", output_values) self.assign_fdb_output_to_nodes(output_values, complete_fdb_decoding_info) @@ -124,7 +126,7 @@ def get_fdb_requests( # First when request node is root, go to its children if requests.axis.name == "root": - logging.info("Looking for data for the tree: %s", [leaf.flatten() for leaf in requests.leaves]) + logging.debug("Looking for data for the tree: %s", [leaf.flatten() for leaf in requests.leaves]) for c in requests.children: self.get_fdb_requests(c, fdb_requests, fdb_requests_decoding_info) @@ -161,8 +163,8 @@ def remove_duplicates_in_request_ranges(self, fdb_node_ranges, current_start_idx new_current_start_idx = [] for j, idx in enumerate(sub_lat_idxs): if idx not in seen_indices: - # TODO: need to remove it from the values in the corresponding tree node - # TODO: need to read just the range we give to gj ... DONE? + # NOTE: need to remove it from the values in the corresponding tree node + # NOTE: need to read just the range we give to gj original_fdb_node_range_vals.append(actual_fdb_node[0].values[j]) seen_indices.add(idx) new_current_start_idx.append(idx) @@ -187,8 +189,6 @@ def nearest_lat_lon_search(self, requests): second_ax = requests.children[0].children[0].axis - # TODO: actually, here we should not remap the nearest_pts, we should instead unmap the - # found_latlon_pts and then remap them later once we have compared found_latlon_pts and nearest_pts nearest_pts = [ [lat_val, second_ax._remap_val_to_axis_range(lon_val)] for (lat_val, lon_val) in zip( @@ -325,8 +325,6 @@ def sort_fdb_request_ranges(self, current_start_idx, lat_length, fdb_node_ranges request_ranges_with_idx = list(enumerate(interm_request_ranges)) sorted_list = sorted(request_ranges_with_idx, key=lambda x: x[1][0]) original_indices, sorted_request_ranges = zip(*sorted_list) - logging.debug("We sorted the request ranges into: %s", sorted_request_ranges) - logging.debug("The sorted and unique leaf node ranges are: %s", new_fdb_node_ranges) return (original_indices, sorted_request_ranges, new_fdb_node_ranges) def datacube_natural_indexes(self, axis, subarray): diff --git a/polytope/datacube/backends/mock.py b/polytope_feature/datacube/backends/mock.py similarity index 94% rename from polytope/datacube/backends/mock.py rename to polytope_feature/datacube/backends/mock.py index 1a48360eb..c23b80802 100644 --- a/polytope/datacube/backends/mock.py +++ b/polytope_feature/datacube/backends/mock.py @@ -24,10 +24,12 @@ def __init__(self, dimensions, compressed_axes_options=[]): self.stride[k] = stride_cumulative stride_cumulative *= self.dimensions[k] - def get(self, requests: TensorIndexTree): + def get(self, requests: TensorIndexTree, context=None): # Takes in a datacube and verifies the leaves of the tree are complete # (ie it found values for all datacube axis) + if context is None: + context = {} for r in requests.leaves: path = r.flatten() if len(path.items()) == len(self.dimensions.items()): diff --git a/polytope/datacube/backends/xarray.py b/polytope_feature/datacube/backends/xarray.py similarity index 95% rename from polytope/datacube/backends/xarray.py rename to polytope_feature/datacube/backends/xarray.py index c01ea52bc..2b7d579de 100644 --- a/polytope/datacube/backends/xarray.py +++ b/polytope_feature/datacube/backends/xarray.py @@ -50,12 +50,14 @@ def __init__(self, dataarray: xr.DataArray, axis_options=None, compressed_axes_o val = self._axes[name].type self._check_and_add_axes(options, name, val) - def get(self, requests, leaf_path=None, axis_counter=0): + def get(self, requests, context=None, leaf_path=None, axis_counter=0): + if context is None: + context = {} if leaf_path is None: leaf_path = {} if requests.axis.name == "root": for c in requests.children: - self.get(c, leaf_path, axis_counter + 1) + self.get(c, context, leaf_path, axis_counter + 1) else: key_value_path = {requests.axis.name: requests.values} ax = requests.axis @@ -66,7 +68,7 @@ def get(self, requests, leaf_path=None, axis_counter=0): if len(requests.children) != 0: # We are not a leaf and we loop over for c in requests.children: - self.get(c, leaf_path, axis_counter + 1) + self.get(c, context, leaf_path, axis_counter + 1) else: if self.axis_counter != axis_counter: requests.remove_branch() diff --git a/polytope/datacube/datacube_axis.py b/polytope_feature/datacube/datacube_axis.py similarity index 100% rename from polytope/datacube/datacube_axis.py rename to polytope_feature/datacube/datacube_axis.py diff --git a/polytope/datacube/index_tree.proto b/polytope_feature/datacube/index_tree.proto similarity index 100% rename from polytope/datacube/index_tree.proto rename to polytope_feature/datacube/index_tree.proto diff --git a/polytope/datacube/index_tree_pb2.py b/polytope_feature/datacube/index_tree_pb2.py similarity index 100% rename from polytope/datacube/index_tree_pb2.py rename to polytope_feature/datacube/index_tree_pb2.py diff --git a/polytope/datacube/tensor_index_tree.py b/polytope_feature/datacube/tensor_index_tree.py similarity index 99% rename from polytope/datacube/tensor_index_tree.py rename to polytope_feature/datacube/tensor_index_tree.py index 380bba7cd..efc35c3e4 100644 --- a/polytope/datacube/tensor_index_tree.py +++ b/polytope_feature/datacube/tensor_index_tree.py @@ -106,6 +106,7 @@ def add_child(self, node): def add_value(self, value): new_values = list(self.values) new_values.append(value) + new_values.sort() self.values = tuple(new_values) def create_child(self, axis, value, next_nodes, polytope_label=None): diff --git a/polytope/datacube/transformations/__init__.py b/polytope_feature/datacube/transformations/__init__.py similarity index 100% rename from polytope/datacube/transformations/__init__.py rename to polytope_feature/datacube/transformations/__init__.py diff --git a/polytope/datacube/transformations/datacube_cyclic/__init__.py b/polytope_feature/datacube/transformations/datacube_cyclic/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_cyclic/__init__.py rename to polytope_feature/datacube/transformations/datacube_cyclic/__init__.py diff --git a/polytope/datacube/transformations/datacube_cyclic/datacube_cyclic.py b/polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py similarity index 100% rename from polytope/datacube/transformations/datacube_cyclic/datacube_cyclic.py rename to polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py diff --git a/polytope/datacube/transformations/datacube_mappers/__init__.py b/polytope_feature/datacube/transformations/datacube_mappers/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_mappers/__init__.py rename to polytope_feature/datacube/transformations/datacube_mappers/__init__.py diff --git a/polytope/datacube/transformations/datacube_mappers/datacube_mappers.py b/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py similarity index 90% rename from polytope/datacube/transformations/datacube_mappers/datacube_mappers.py rename to polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py index f79d43de3..e0792ac5f 100644 --- a/polytope/datacube/transformations/datacube_mappers/datacube_mappers.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py @@ -15,17 +15,25 @@ def __init__(self, name, mapper_options): self.local_area = [] if mapper_options.local is not None: self.local_area = mapper_options.local + self._axis_reversed = None + if mapper_options.axis_reversed is not None: + self._axis_reversed = mapper_options.axis_reversed self.old_axis = name self._final_transformation = self.generate_final_transformation() self._final_mapped_axes = self._final_transformation._mapped_axes self._axis_reversed = self._final_transformation._axis_reversed self.compressed_grid_axes = self._final_transformation.compressed_grid_axes + self.md5_hash = self._final_transformation.md5_hash def generate_final_transformation(self): map_type = _type_to_datacube_mapper_lookup[self.grid_type] - module = import_module("polytope.datacube.transformations.datacube_mappers.mapper_types." + self.grid_type) + module = import_module( + "polytope_feature.datacube.transformations.datacube_mappers.mapper_types." + self.grid_type + ) constructor = getattr(module, map_type) - transformation = deepcopy(constructor(self.old_axis, self.grid_axes, self.grid_resolution, self.local_area)) + transformation = deepcopy( + constructor(self.old_axis, self.grid_axes, self.grid_resolution, self.local_area, self._axis_reversed) + ) return transformation def blocked_axes(self): diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/__init__.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/__init__.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py similarity index 91% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/healpix.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py index b198a157a..a6a0b46e0 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py @@ -5,7 +5,7 @@ class HealpixGridMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis @@ -13,6 +13,11 @@ def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False} self._first_axis_vals = self.first_axis_vals() self.compressed_grid_axes = [self._mapped_axes[1]] + self.md5_hash = md5_hash.get(resolution, None) + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Healpix grid with second axis in decreasing order is not supported") + if not self._axis_reversed[mapped_axes[0]]: + raise NotImplementedError("Healpix grid with first axis in increasing order is not supported") def first_axis_vals(self): rad2deg = 180 / math.pi @@ -133,3 +138,7 @@ def unmap(self, first_val, second_val): second_idx = self.second_axis_vals(first_val).index(second_val) healpix_index = self.axes_idx_to_healpix_idx(first_idx, second_idx) return healpix_index + + +# md5 grid hash in form {resolution : hash} +md5_hash = {} diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py similarity index 94% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py index abbd01392..c0aff8f43 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py @@ -5,7 +5,7 @@ class NestedHealpixGridMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis @@ -17,6 +17,11 @@ def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): self.k = int(math.log2(self.Nside)) self.Npix = 12 * self.Nside * self.Nside self.Ncap = (self.Nside * (self.Nside - 1)) << 1 + self.md5_hash = md5_hash.get(resolution, None) + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Healpix grid with second axis in decreasing order is not supported") + if not self._axis_reversed[mapped_axes[0]]: + raise NotImplementedError("Healpix grid with first axis in increasing order is not supported") def first_axis_vals(self): rad2deg = 180 / math.pi @@ -211,3 +216,7 @@ def ring_to_nested(self, idx): def int_sqrt(self, i): return int(math.sqrt(i + 0.5)) + + +# md5 grid hash in form {resolution : hash} +md5_hash = {} diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/local_regular.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py similarity index 74% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/local_regular.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py index 40f86bfbd..99fcc4058 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py @@ -4,7 +4,7 @@ class LocalRegularGridMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis @@ -15,17 +15,32 @@ def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): if not isinstance(resolution, list): self.first_resolution = resolution self.second_resolution = resolution + self.md5_hash = md5_hash.get(resolution, None) else: self.first_resolution = resolution[0] self.second_resolution = resolution[1] + self.md5_hash = md5_hash.get(tuple(resolution), None) self._first_deg_increment = (local_area[1] - local_area[0]) / self.first_resolution self._second_deg_increment = (local_area[3] - local_area[2]) / self.second_resolution - self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False} + if axis_reversed is None: + self._axis_reversed = {mapped_axes[0]: False, mapped_axes[1]: False} + else: + assert set(axis_reversed.keys()) == set(mapped_axes) + self._axis_reversed = axis_reversed self._first_axis_vals = self.first_axis_vals() self.compressed_grid_axes = [self._mapped_axes[1]] + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Local regular grid with second axis in decreasing order is not supported") def first_axis_vals(self): - first_ax_vals = [self._first_axis_max - i * self._first_deg_increment for i in range(self.first_resolution + 1)] + if self._axis_reversed[self._mapped_axes[0]]: + first_ax_vals = [ + self._first_axis_max - i * self._first_deg_increment for i in range(self.first_resolution + 1) + ] + else: + first_ax_vals = [ + self._first_axis_min + i * self._first_deg_increment for i in range(self.first_resolution + 1) + ] return first_ax_vals def map_first_axis(self, lower, upper): @@ -68,3 +83,7 @@ def unmap(self, first_val, second_val): second_idx = self.second_axis_vals(first_val).index(second_val) final_index = self.axes_idx_to_regular_idx(first_idx, second_idx) return final_index + + +# md5 grid hash in form {resolution : hash} +md5_hash = {} diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/octahedral.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py similarity index 99% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/octahedral.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py index f48fca712..e1a4ac01b 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py @@ -5,7 +5,7 @@ class OctahedralGridMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis @@ -14,7 +14,12 @@ def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): self._first_idx_map = self.create_first_idx_map() self._second_axis_spacing = {} self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False} + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Octahedral grid with second axis in decreasing order is not supported") + if not self._axis_reversed[mapped_axes[0]]: + raise NotImplementedError("Octahedral grid with first axis in increasing order is not supported") self.compressed_grid_axes = [self._mapped_axes[1]] + self.md5_hash = md5_hash.get(resolution, None) def gauss_first_guess(self): i = 0 @@ -2750,3 +2755,9 @@ def unmap(self, first_val, second_val): (first_idx, second_idx) = self.find_second_axis_idx(first_val, second_val) octahedral_index = self.axes_idx_to_octahedral_idx(first_idx, second_idx) return octahedral_index + + +# md5 grid hash in form {resolution : hash} +md5_hash = { + 1280: "158db321ae8e773681eeb40e0a3d350f", +} diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py similarity index 98% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py index 5a76f5d10..115519ce2 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py @@ -4,7 +4,7 @@ class ReducedLatLonMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis @@ -12,6 +12,11 @@ def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): self._axis_reversed = {mapped_axes[0]: False, mapped_axes[1]: False} self._first_axis_vals = self.first_axis_vals() self.compressed_grid_axes = [self._mapped_axes[1]] + self.md5_hash = md5_hash.get(resolution, None) + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Reduced lat-lon grid with second axis in decreasing order is not supported") + if self._axis_reversed[mapped_axes[0]]: + raise NotImplementedError("Reduced lat-lon grid with first axis in decreasing order is not supported") def first_axis_vals(self): resolution = 180 / (self._resolution - 1) @@ -1504,3 +1509,7 @@ def unmap(self, first_val, second_val): second_idx = self.second_axis_vals(first_val).index(second_val) reduced_ll_index = self.axes_idx_to_reduced_ll_idx(first_idx, second_idx) return reduced_ll_index + + +# md5 grid hash in form {resolution : hash} +md5_hash = {} diff --git a/polytope/datacube/transformations/datacube_mappers/mapper_types/regular.py b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py similarity index 74% rename from polytope/datacube/transformations/datacube_mappers/mapper_types/regular.py rename to polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py index 3b40f77e4..11fcb4fc9 100644 --- a/polytope/datacube/transformations/datacube_mappers/mapper_types/regular.py +++ b/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py @@ -4,18 +4,28 @@ class RegularGridMapper(DatacubeMapper): - def __init__(self, base_axis, mapped_axes, resolution, local_area=[]): + def __init__(self, base_axis, mapped_axes, resolution, local_area=[], axis_reversed=None): # TODO: if local area is not empty list, raise NotImplemented self._mapped_axes = mapped_axes self._base_axis = base_axis self._resolution = resolution self.deg_increment = 90 / self._resolution - self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False} + if axis_reversed is None: + self._axis_reversed = {mapped_axes[0]: True, mapped_axes[1]: False} + else: + assert set(axis_reversed.keys()) == set(mapped_axes) + self._axis_reversed = axis_reversed self._first_axis_vals = self.first_axis_vals() self.compressed_grid_axes = [self._mapped_axes[1]] + self.md5_hash = md5_hash.get(resolution, None) + if self._axis_reversed[mapped_axes[1]]: + raise NotImplementedError("Regular grid with second axis in decreasing order is not supported") def first_axis_vals(self): - first_ax_vals = [90 - i * self.deg_increment for i in range(2 * self._resolution)] + if self._axis_reversed[self._mapped_axes[0]]: + first_ax_vals = [90 - i * self.deg_increment for i in range(2 * self._resolution)] + else: + first_ax_vals = [-90 + i * self.deg_increment for i in range(2 * self._resolution)] return first_ax_vals def map_first_axis(self, lower, upper): @@ -56,3 +66,7 @@ def unmap(self, first_val, second_val): second_idx = self.second_axis_vals(first_val).index(second_val) final_index = self.axes_idx_to_regular_idx(first_idx, second_idx) return final_index + + +# md5 grid hash in form {resolution : hash} +md5_hash = {} diff --git a/polytope/datacube/transformations/datacube_merger/__init__.py b/polytope_feature/datacube/transformations/datacube_merger/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_merger/__init__.py rename to polytope_feature/datacube/transformations/datacube_merger/__init__.py diff --git a/polytope/datacube/transformations/datacube_merger/datacube_merger.py b/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py similarity index 97% rename from polytope/datacube/transformations/datacube_merger/datacube_merger.py rename to polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py index 717237a33..5b0516638 100644 --- a/polytope/datacube/transformations/datacube_merger/datacube_merger.py +++ b/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py @@ -93,6 +93,5 @@ def unmap_tree_node(self, node, unwanted_path): if node.axis.name == self._first_axis: (new_first_vals, new_second_vals) = self.unmerge(node.values) node.values = new_first_vals - # TODO: actually need to give the second axis of the transformation to get the interm axis interm_node = node.add_node_layer_after(self._second_axis, new_second_vals) return (interm_node, unwanted_path) diff --git a/polytope/datacube/transformations/datacube_reverse/__init__.py b/polytope_feature/datacube/transformations/datacube_reverse/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_reverse/__init__.py rename to polytope_feature/datacube/transformations/datacube_reverse/__init__.py diff --git a/polytope/datacube/transformations/datacube_reverse/datacube_reverse.py b/polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py similarity index 100% rename from polytope/datacube/transformations/datacube_reverse/datacube_reverse.py rename to polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py diff --git a/polytope/datacube/transformations/datacube_transformations.py b/polytope_feature/datacube/transformations/datacube_transformations.py similarity index 94% rename from polytope/datacube/transformations/datacube_transformations.py rename to polytope_feature/datacube/transformations/datacube_transformations.py index 34af22550..f174bf1aa 100644 --- a/polytope/datacube/transformations/datacube_transformations.py +++ b/polytope_feature/datacube/transformations/datacube_transformations.py @@ -12,9 +12,8 @@ def create_transform(name, transformation_type_key, transformation_options): transformation_type = _type_to_datacube_transformation_lookup[transformation_type_key] transformation_file_name = _type_to_transformation_file_lookup[transformation_type_key] file_name = ".datacube_" + transformation_file_name - module = import_module("polytope.datacube.transformations" + file_name + file_name) + module = import_module("polytope_feature.datacube.transformations" + file_name + file_name) constructor = getattr(module, transformation_type) - # transformation_type_option = transformation_options[transformation_type_key] transformation_type_option = transformation_options new_transformation = deepcopy(constructor(name, transformation_type_option)) diff --git a/polytope/datacube/transformations/datacube_type_change/__init__.py b/polytope_feature/datacube/transformations/datacube_type_change/__init__.py similarity index 100% rename from polytope/datacube/transformations/datacube_type_change/__init__.py rename to polytope_feature/datacube/transformations/datacube_type_change/__init__.py diff --git a/polytope/datacube/transformations/datacube_type_change/datacube_type_change.py b/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py similarity index 95% rename from polytope/datacube/transformations/datacube_type_change/datacube_type_change.py rename to polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py index 8cbf2c44e..7d6cc4cd2 100644 --- a/polytope/datacube/transformations/datacube_type_change/datacube_type_change.py +++ b/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py @@ -15,7 +15,7 @@ def __init__(self, name, type_options): def generate_final_transformation(self): map_type = _type_to_datacube_type_change_lookup[self.new_type] - module = import_module("polytope.datacube.transformations.datacube_type_change.datacube_type_change") + module = import_module("polytope_feature.datacube.transformations.datacube_type_change.datacube_type_change") constructor = getattr(module, map_type) transformation = deepcopy(constructor(self.name, self.new_type)) return transformation diff --git a/polytope/datacube/tree_encoding.py b/polytope_feature/datacube/tree_encoding.py similarity index 100% rename from polytope/datacube/tree_encoding.py rename to polytope_feature/datacube/tree_encoding.py diff --git a/polytope/engine/__init__.py b/polytope_feature/engine/__init__.py similarity index 100% rename from polytope/engine/__init__.py rename to polytope_feature/engine/__init__.py diff --git a/polytope/engine/engine.py b/polytope_feature/engine/engine.py similarity index 100% rename from polytope/engine/engine.py rename to polytope_feature/engine/engine.py diff --git a/polytope/engine/hullslicer.py b/polytope_feature/engine/hullslicer.py similarity index 84% rename from polytope/engine/hullslicer.py rename to polytope_feature/engine/hullslicer.py index c29179a8e..d596004cb 100644 --- a/polytope/engine/hullslicer.py +++ b/polytope_feature/engine/hullslicer.py @@ -110,7 +110,7 @@ def remap_values(self, ax, value): def _build_sliceable_child(self, polytope, ax, node, datacube, values, next_nodes, slice_axis_idx): for i, value in enumerate(values): - if i == 0: + if i == 0 or ax.name not in self.compressed_axes: fvalue = ax.to_float(value) new_polytope = slice(polytope, ax.name, fvalue, slice_axis_idx) remapped_val = self.remap_values(ax, value) @@ -122,20 +122,8 @@ def _build_sliceable_child(self, polytope, ax, node, datacube, values, next_node child["unsliced_polytopes"].add(new_polytope) next_nodes.append(child) else: - if ax.name not in self.compressed_axes: - fvalue = ax.to_float(value) - new_polytope = slice(polytope, ax.name, fvalue, slice_axis_idx) - polytope_label = polytope.label - remapped_val = self.remap_values(ax, value) - (child, next_nodes) = node.create_child(ax, remapped_val, next_nodes, polytope_label) - child["unsliced_polytopes"] = copy(node["unsliced_polytopes"]) - child["unsliced_polytopes"].remove(polytope) - if new_polytope is not None: - child["unsliced_polytopes"].add(new_polytope) - next_nodes.append(child) - else: - remapped_val = self.remap_values(ax, value) - child.add_value(remapped_val) + remapped_val = self.remap_values(ax, value) + child.add_value(remapped_val) def _build_branch(self, ax, node, datacube, next_nodes): if ax.name not in self.compressed_axes: @@ -144,26 +132,23 @@ def _build_branch(self, ax, node, datacube, next_nodes): for polytope in node["unsliced_polytopes"]: if ax.name in polytope._axes: right_unsliced_polytopes.append(polytope) - # for polytope in node["unsliced_polytopes"]: for i, polytope in enumerate(right_unsliced_polytopes): node._parent = parent_node - # if ax.name in polytope._axes: - if True: - lower, upper, slice_axis_idx = polytope.extents(ax.name) - # here, first check if the axis is an unsliceable axis and directly build node if it is - # NOTE: we should have already created the ax_is_unsliceable cache before - if self.ax_is_unsliceable[ax.name]: - self._build_unsliceable_child(polytope, ax, node, datacube, [lower], next_nodes, slice_axis_idx) - else: - values = self.find_values_between(polytope, ax, node, datacube, lower, upper) - # NOTE: need to only remove the branches if the values are empty, - # but only if there are no other possible children left in the tree that - # we can append and if somehow this happens before and we need to remove, then what do we do?? - if i == len(right_unsliced_polytopes) - 1: - # we have iterated all polytopes and we can now remove the node if we need to - if len(values) == 0 and len(node.children) == 0: - node.remove_branch() - self._build_sliceable_child(polytope, ax, node, datacube, values, next_nodes, slice_axis_idx) + lower, upper, slice_axis_idx = polytope.extents(ax.name) + # here, first check if the axis is an unsliceable axis and directly build node if it is + # NOTE: we should have already created the ax_is_unsliceable cache before + if self.ax_is_unsliceable[ax.name]: + self._build_unsliceable_child(polytope, ax, node, datacube, [lower], next_nodes, slice_axis_idx) + else: + values = self.find_values_between(polytope, ax, node, datacube, lower, upper) + # NOTE: need to only remove the branches if the values are empty, + # but only if there are no other possible children left in the tree that + # we can append and if somehow this happens before and we need to remove, then what do we do?? + if i == len(right_unsliced_polytopes) - 1: + # we have iterated all polytopes and we can now remove the node if we need to + if len(values) == 0 and len(node.children) == 0: + node.remove_branch() + self._build_sliceable_child(polytope, ax, node, datacube, values, next_nodes, slice_axis_idx) else: all_values = [] all_lowers = [] @@ -217,7 +202,6 @@ def remove_compressed_axis_in_union(self, polytopes): for p in polytopes: if p.is_in_union: for axis in p.axes(): - # if axis in self.compressed_axes: if axis == self.compressed_axes[-1]: self.compressed_axes.remove(axis) diff --git a/polytope_feature/options.py b/polytope_feature/options.py new file mode 100644 index 000000000..174a377c0 --- /dev/null +++ b/polytope_feature/options.py @@ -0,0 +1,79 @@ +import argparse +from abc import ABC +from typing import Dict, List, Literal, Optional, Union + +from conflator import ConfigModel, Conflator +from pydantic import ConfigDict + + +class TransformationConfig(ConfigModel): + model_config = ConfigDict(extra="forbid") + name: str = "" + + +class CyclicConfig(TransformationConfig): + name: Literal["cyclic"] + range: List[float] = [0] + + +class MapperConfig(TransformationConfig): + name: Literal["mapper"] + type: str = "" + resolution: Union[int, List[int]] = 0 + axes: List[str] = [""] + local: Optional[List[float]] = None + axis_reversed: Optional[Dict[str, bool]] = None + + +class ReverseConfig(TransformationConfig): + name: Literal["reverse"] + is_reverse: bool = False + + +class TypeChangeConfig(TransformationConfig): + name: Literal["type_change"] + type: str = "int" + + +class MergeConfig(TransformationConfig): + name: Literal["merge"] + other_axis: str = "" + linkers: List[str] = [""] + + +action_subclasses_union = Union[CyclicConfig, MapperConfig, ReverseConfig, TypeChangeConfig, MergeConfig] + + +class AxisConfig(ConfigModel): + axis_name: str = "" + transformations: list[action_subclasses_union] + + +path_subclasses_union = Union[str, int, float] + + +class GribJumpAxesConfig(ConfigModel): + axis_name: str = "" + values: List[str] = [""] + + +class Config(ConfigModel): + axis_config: List[AxisConfig] = [] + compressed_axes_config: List[str] = [""] + pre_path: Optional[Dict[str, path_subclasses_union]] = {} + alternative_axes: List[GribJumpAxesConfig] = [] + + +class PolytopeOptions(ABC): + @staticmethod + def get_polytope_options(options): + parser = argparse.ArgumentParser(allow_abbrev=False) + conflator = Conflator(app_name="polytope", model=Config, cli=False, argparser=parser, **options) + config_options = conflator.load() + + axis_config = config_options.axis_config + compressed_axes_config = config_options.compressed_axes_config + pre_path = config_options.pre_path + alternative_axes = config_options.alternative_axes + + return (axis_config, compressed_axes_config, pre_path, alternative_axes) diff --git a/polytope/polytope.py b/polytope_feature/polytope.py similarity index 85% rename from polytope/polytope.py rename to polytope_feature/polytope.py index 271725471..29a03d631 100644 --- a/polytope/polytope.py +++ b/polytope_feature/polytope.py @@ -1,3 +1,4 @@ +import logging from typing import List from .options import PolytopeOptions @@ -55,9 +56,14 @@ def slice(self, polytopes: List[ConvexPolytope]): """Low-level API which takes a polytope geometry object and uses it to slice the datacube""" return self.engine.extract(self.datacube, polytopes) - def retrieve(self, request: Request, method="standard"): + def retrieve(self, request: Request, method="standard", context=None): """Higher-level API which takes a request and uses it to slice the datacube""" + if context is None: + context = {} + logging.info("Starting request for %s ", context) self.datacube.check_branching_axes(request) request_tree = self.engine.extract(self.datacube, request.polytopes()) - self.datacube.get(request_tree) + logging.info("Created request tree for %s ", context) + self.datacube.get(request_tree, context) + logging.info("Retrieved data for %s ", context) return request_tree diff --git a/polytope/shapes.py b/polytope_feature/shapes.py similarity index 100% rename from polytope/shapes.py rename to polytope_feature/shapes.py diff --git a/polytope/utility/__init__.py b/polytope_feature/utility/__init__.py similarity index 100% rename from polytope/utility/__init__.py rename to polytope_feature/utility/__init__.py diff --git a/polytope/utility/combinatorics.py b/polytope_feature/utility/combinatorics.py similarity index 100% rename from polytope/utility/combinatorics.py rename to polytope_feature/utility/combinatorics.py diff --git a/polytope/utility/exceptions.py b/polytope_feature/utility/exceptions.py similarity index 73% rename from polytope/utility/exceptions.py rename to polytope_feature/utility/exceptions.py index fb30f627d..b9b25e0fb 100644 --- a/polytope/utility/exceptions.py +++ b/polytope_feature/utility/exceptions.py @@ -1,4 +1,8 @@ -class AxisOverdefinedError(KeyError): +class PolytopeError(Exception): + pass + + +class AxisOverdefinedError(PolytopeError, KeyError): def __init__(self, axis): self.axis = axis self.message = ( @@ -7,19 +11,19 @@ def __init__(self, axis): ) -class AxisUnderdefinedError(KeyError): +class AxisUnderdefinedError(PolytopeError, KeyError): def __init__(self, axis): self.axis = axis self.message = f"Axis {axis} is underdefined. It does not appear in any input polytope." -class AxisNotFoundError(KeyError): +class AxisNotFoundError(PolytopeError, KeyError): def __init__(self, axis): self.axis = axis self.message = f"Axis {axis} does not exist in the datacube." -class UnsliceableShapeError(KeyError): +class UnsliceableShapeError(PolytopeError, KeyError): def __init__(self, axis): self.axis = axis self.message = f"Higher-dimensional shape does not support unsliceable axis {axis.name}." diff --git a/polytope/utility/geometry.py b/polytope_feature/utility/geometry.py similarity index 100% rename from polytope/utility/geometry.py rename to polytope_feature/utility/geometry.py diff --git a/polytope/utility/list_tools.py b/polytope_feature/utility/list_tools.py similarity index 100% rename from polytope/utility/list_tools.py rename to polytope_feature/utility/list_tools.py diff --git a/polytope/utility/profiling.py b/polytope_feature/utility/profiling.py similarity index 100% rename from polytope/utility/profiling.py rename to polytope_feature/utility/profiling.py diff --git a/polytope_feature/version.py b/polytope_feature/version.py new file mode 100644 index 000000000..e13bd590c --- /dev/null +++ b/polytope_feature/version.py @@ -0,0 +1 @@ +__version__ = "1.0.8" diff --git a/serializedTree b/serializedTree deleted file mode 100644 index 4bb27cb8d..000000000 Binary files a/serializedTree and /dev/null differ diff --git a/setup.py b/setup.py index 005e76dfd..06c058056 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ __version__ = re.search( r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', - io.open("polytope/version.py", encoding="utf_8_sig").read(), + io.open("polytope_feature/version.py", encoding="utf_8_sig").read(), ).group(1) with open("requirements.txt") as f: diff --git a/tests/test_axis_mappers.py b/tests/test_axis_mappers.py index c1dc0cd24..b500b9a03 100644 --- a/tests/test_axis_mappers.py +++ b/tests/test_axis_mappers.py @@ -1,13 +1,13 @@ import pandas as pd -from polytope.datacube.datacube_axis import ( +from polytope_feature.datacube.datacube_axis import ( DatacubeAxisCyclic, FloatDatacubeAxis, IntDatacubeAxis, PandasTimedeltaDatacubeAxis, PandasTimestampDatacubeAxis, ) -from polytope.options import PolytopeOptions +from polytope_feature.options import PolytopeOptions class TestAxisMappers: diff --git a/tests/test_combinatorics.py b/tests/test_combinatorics.py index 980ad8e2c..0e4798720 100644 --- a/tests/test_combinatorics.py +++ b/tests/test_combinatorics.py @@ -1,9 +1,9 @@ import numpy as np import pytest -from polytope import ConvexPolytope -from polytope.utility.combinatorics import group, tensor_product, validate_axes -from polytope.utility.exceptions import ( +from polytope_feature import ConvexPolytope +from polytope_feature.utility.combinatorics import group, tensor_product, validate_axes +from polytope_feature.utility.exceptions import ( AxisNotFoundError, AxisOverdefinedError, AxisUnderdefinedError, diff --git a/tests/test_cyclic_axis_over_negative_vals.py b/tests/test_cyclic_axis_over_negative_vals.py index 24d30b636..37bddd75f 100644 --- a/tests/test_cyclic_axis_over_negative_vals.py +++ b/tests/test_cyclic_axis_over_negative_vals.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingCyclicAxisNegVals: @@ -40,7 +40,6 @@ def test_cyclic_float_axis_across_seam(self): result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ - (-0.2,), (-1.1,), (-1.0,), (-0.9,), @@ -50,6 +49,7 @@ def test_cyclic_float_axis_across_seam(self): (-0.5,), (-0.4,), (-0.3,), + (-0.2,), ] def test_cyclic_float_axis_inside_cyclic_range(self): @@ -93,31 +93,31 @@ def test_cyclic_float_axis_two_range_loops(self): result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ - (-0.7,), - (-0.6,), - (-0.5,), - (-0.4,), - (-0.3,), - (-0.2,), (-1.1,), - (-1.0,), - (-0.9,), - (-0.8,), - (-0.7,), - (-0.6,), - (-0.5,), - (-0.4,), - (-0.3,), - (-0.2,), (-1.1,), (-1.0,), + (-1.0,), (-0.9,), + (-0.9,), + (-0.8,), (-0.8,), (-0.7,), + (-0.7,), + (-0.7,), + (-0.6,), (-0.6,), + (-0.6,), + (-0.5,), (-0.5,), + (-0.5,), + (-0.4,), + (-0.4,), (-0.4,), (-0.3,), + (-0.3,), + (-0.3,), + (-0.2,), + (-0.2,), ] def test_cyclic_float_axis_below_axis_range(self): @@ -142,6 +142,10 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): # result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ + (-1.0,), + (-0.9,), + (-0.8,), + (-0.7,), (-0.7,), (-0.6,), (-0.5,), @@ -149,8 +153,4 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): (-0.3,), (-0.2,), (-0.1,), - (-1.0,), - (-0.9,), - (-0.8,), - (-0.7,), ] diff --git a/tests/test_cyclic_axis_slicer_not_0.py b/tests/test_cyclic_axis_slicer_not_0.py index 5a117c8e3..84d36d9ce 100644 --- a/tests/test_cyclic_axis_slicer_not_0.py +++ b/tests/test_cyclic_axis_slicer_not_0.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingCyclicAxisNotOverZero: @@ -44,7 +44,6 @@ def test_cyclic_float_axis_across_seam(self): result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ - (-0.2,), (-1.1,), (-1.0,), (-0.9,), @@ -54,6 +53,7 @@ def test_cyclic_float_axis_across_seam(self): (-0.5,), (-0.4,), (-0.3,), + (-0.2,), ] def test_cyclic_float_axis_inside_cyclic_range(self): @@ -94,31 +94,31 @@ def test_cyclic_float_axis_two_range_loops(self): result = self.API.retrieve(request) assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ - (-0.7,), - (-0.6,), - (-0.5,), - (-0.4,), - (-0.3,), - (-0.2,), (-1.1,), - (-1.0,), - (-0.9,), - (-0.8,), - (-0.7,), - (-0.6,), - (-0.5,), - (-0.4,), - (-0.3,), - (-0.2,), (-1.1,), (-1.0,), + (-1.0,), (-0.9,), + (-0.9,), + (-0.8,), (-0.8,), (-0.7,), + (-0.7,), + (-0.7,), + (-0.6,), (-0.6,), + (-0.6,), + (-0.5,), (-0.5,), + (-0.5,), + (-0.4,), + (-0.4,), (-0.4,), (-0.3,), + (-0.3,), + (-0.3,), + (-0.2,), + (-0.2,), ] def test_cyclic_float_axis_below_axis_range(self): @@ -142,6 +142,10 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): result = self.API.retrieve(request) assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ + (-1.0,), + (-0.9,), + (-0.8,), + (-0.7,), (-0.7,), (-0.6,), (-0.5,), @@ -149,8 +153,4 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): (-0.3,), (-0.2,), (-0.1,), - (-1.0,), - (-0.9,), - (-0.8,), - (-0.7,), ] diff --git a/tests/test_cyclic_axis_slicing.py b/tests/test_cyclic_axis_slicing.py index 2ad154315..3f8d53e8d 100644 --- a/tests/test_cyclic_axis_slicing.py +++ b/tests/test_cyclic_axis_slicing.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingCyclic: @@ -44,9 +44,6 @@ def test_cyclic_float_axis_across_seam(self): assert len(result.leaves) == 1 result.pprint() assert [(val,) for val in result.leaves[0].values] == [ - (0.8,), - (0.9,), - (1.0,), (0.1,), (0.2,), (0.3,), @@ -54,6 +51,9 @@ def test_cyclic_float_axis_across_seam(self): (0.5,), (0.6,), (0.7,), + (0.8,), + (0.9,), + (1.0,), ] def test_cyclic_float_axis_across_seam_repeated(self): @@ -85,27 +85,27 @@ def test_cyclic_float_axis_across_seam_repeated_twice(self): result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ + (0.0,), (0.0,), (0.1,), - (0.2,), - (0.3,), - (0.4,), - (0.5,), - (0.6,), - (0.7,), - (0.8,), - (0.9,), - (1.0,), (0.1,), (0.2,), + (0.2,), (0.3,), + (0.3,), + (0.4,), (0.4,), (0.5,), + (0.5,), + (0.6,), (0.6,), (0.7,), + (0.7,), + (0.8,), (0.8,), (0.9,), - (0.0,), + (0.9,), + (1.0,), ] def test_cyclic_float_axis_inside_cyclic_range(self): @@ -151,31 +151,31 @@ def test_cyclic_float_axis_two_range_loops(self): # result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ - (0.3,), - (0.4,), - (0.5,), - (0.6,), - (0.7,), - (0.8,), - (0.9,), - (1.0,), + (0.0,), + (0.1,), (0.1,), (0.2,), + (0.2,), + (0.3,), (0.3,), + (0.3,), + (0.4,), (0.4,), + (0.4,), + (0.5,), (0.5,), + (0.5,), + (0.6,), (0.6,), + (0.6,), + (0.7,), (0.7,), + (0.7,), + (0.8,), (0.8,), (0.9,), - (0.0,), - (0.1,), - (0.2,), - (0.3,), - (0.4,), - (0.5,), - (0.6,), - (0.7,), + (0.9,), + (1.0,), ] def test_cyclic_float_axis_below_axis_range(self): @@ -201,6 +201,10 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): # result.pprint() assert len(result.leaves) == 1 assert [(val,) for val in result.leaves[0].values] == [ + (0.0,), + (0.1,), + (0.2,), + (0.3,), (0.3,), (0.4,), (0.5,), @@ -208,10 +212,6 @@ def test_cyclic_float_axis_below_axis_range_crossing_seam(self): (0.7,), (0.8,), (0.9,), - (0.0,), - (0.1,), - (0.2,), - (0.3,), ] def test_cyclic_float_axis_reversed(self): diff --git a/tests/test_cyclic_nearest.py b/tests/test_cyclic_nearest.py index fbf7f2996..86e37c69c 100644 --- a/tests/test_cyclic_nearest.py +++ b/tests/test_cyclic_nearest.py @@ -3,9 +3,9 @@ from eccodes import codes_grib_find_nearest, codes_grib_new_from_file from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Point, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Point, Select class TestRegularGrid: diff --git a/tests/test_cyclic_simple.py b/tests/test_cyclic_simple.py index d12e45413..d9974b7e7 100644 --- a/tests/test_cyclic_simple.py +++ b/tests/test_cyclic_simple.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicing3DXarrayDatacube: @@ -43,7 +43,7 @@ def test_cyclic_float_axis_across_seam(self): result = self.API.retrieve(request) result.pprint() assert len(result.leaves) == 1 - assert [leaf.values for leaf in result.leaves] == [(0.9, 1.0, 0.1, 0.2)] + assert [leaf.values for leaf in result.leaves] == [(0.1, 0.2, 0.9, 1.0)] def test_cyclic_float_surrounding(self): request = Request( diff --git a/tests/test_cyclic_snapping.py b/tests/test_cyclic_snapping.py index f81c65405..599dc9573 100644 --- a/tests/test_cyclic_snapping.py +++ b/tests/test_cyclic_snapping.py @@ -1,8 +1,8 @@ import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestSlicing3DXarrayDatacube: @@ -30,7 +30,7 @@ def test_cyclic_float_axis_across_seam(self): result = self.API.retrieve(request) result.pprint() assert len(result.leaves) == 1 - assert result.leaves[0].flatten()["long"] == (0.5, 0.0) + assert result.leaves[0].flatten()["long"] == (0.0, 0.5) assert result.leaves[0].result[0] is None - assert result.leaves[0].result[1][0] == 1 - assert result.leaves[0].result[1][1] == 0 + assert result.leaves[0].result[1][0] == 0 + assert result.leaves[0].result[1][1] == 1 diff --git a/tests/test_datacube_axes_init.py b/tests/test_datacube_axes_init.py index c02c44f84..702374de8 100644 --- a/tests/test_datacube_axes_init.py +++ b/tests/test_datacube_axes_init.py @@ -2,10 +2,10 @@ from earthkit import data from helper_functions import download_test_data -from polytope.datacube.datacube_axis import FloatDatacubeAxis -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.datacube.datacube_axis import FloatDatacubeAxis +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestInitDatacubeAxes: diff --git a/tests/test_datacube_mock.py b/tests/test_datacube_mock.py index 0b147b95c..b941af1d3 100644 --- a/tests/test_datacube_mock.py +++ b/tests/test_datacube_mock.py @@ -1,7 +1,7 @@ import pytest -from polytope.datacube.backends.mock import MockDatacube -from polytope.utility.exceptions import AxisNotFoundError, AxisOverdefinedError +from polytope_feature.datacube.backends.mock import MockDatacube +from polytope_feature.utility.exceptions import AxisNotFoundError, AxisOverdefinedError class TestMockDatacube: diff --git a/tests/test_datacube_xarray.py b/tests/test_datacube_xarray.py index 362937cdd..f15a4f8bc 100644 --- a/tests/test_datacube_xarray.py +++ b/tests/test_datacube_xarray.py @@ -5,14 +5,14 @@ import pytest import xarray as xr -from polytope.datacube import Datacube, DatacubePath -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.datacube.datacube_axis import ( +from polytope_feature.datacube import Datacube, DatacubePath +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.datacube.datacube_axis import ( FloatDatacubeAxis, IntDatacubeAxis, PandasTimestampDatacubeAxis, ) -from polytope.utility.exceptions import AxisNotFoundError, AxisOverdefinedError +from polytope_feature.utility.exceptions import AxisNotFoundError, AxisOverdefinedError class TestXarrayDatacube: diff --git a/tests/test_ecmwf_oper_data_fdb.py b/tests/test_ecmwf_oper_data_fdb.py index c08674638..e848716c8 100644 --- a/tests/test_ecmwf_oper_data_fdb.py +++ b/tests/test_ecmwf_oper_data_fdb.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Point, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Point, Select, Span class TestSlicingFDBDatacube: diff --git a/tests/test_engine_slicer.py b/tests/test_engine_slicer.py index 5e79479e3..3392ccd3a 100644 --- a/tests/test_engine_slicer.py +++ b/tests/test_engine_slicer.py @@ -1,6 +1,6 @@ -from polytope.datacube.backends.mock import MockDatacube -from polytope.engine.hullslicer import HullSlicer -from polytope.shapes import Box, Polygon +from polytope_feature.datacube.backends.mock import MockDatacube +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.shapes import Box, Polygon class TestEngineSlicer: diff --git a/tests/test_fdb_datacube.py b/tests/test_fdb_datacube.py index 777e60f42..301ceec30 100644 --- a/tests/test_fdb_datacube.py +++ b/tests/test_fdb_datacube.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select, Span # import geopandas as gpd # import matplotlib.pyplot as plt diff --git a/tests/test_fdb_unmap_tree.py b/tests/test_fdb_unmap_tree.py index bfc71f1ee..a9dcf9cbe 100644 --- a/tests/test_fdb_unmap_tree.py +++ b/tests/test_fdb_unmap_tree.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingFDBDatacube: diff --git a/tests/test_float_type.py b/tests/test_float_type.py index 222ce458a..51df70df8 100644 --- a/tests/test_float_type.py +++ b/tests/test_float_type.py @@ -2,9 +2,9 @@ import pytest import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select, Span class TestFloatType: diff --git a/tests/test_healpix_mapper.py b/tests/test_healpix_mapper.py index d3d1ac50e..a7b82877c 100644 --- a/tests/test_healpix_mapper.py +++ b/tests/test_healpix_mapper.py @@ -2,15 +2,15 @@ from earthkit import data from helper_functions import download_test_data, find_nearest_latlon -from polytope.datacube.transformations.datacube_mappers.mapper_types.healpix import ( +from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.healpix import ( HealpixGridMapper, ) -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select -class TestOctahedralGrid: +class TestHealpixGrid: def setup_method(self, method): nexus_url = "https://get.ecmwf.int/test-data/polytope/test-data/healpix.grib" download_test_data(nexus_url, "healpix.grib") @@ -69,7 +69,7 @@ def test_healpix_grid(self): eccodes_lon = nearest_points[0][0]["lon"] eccodes_result = nearest_points[0][0]["value"] - mapper = HealpixGridMapper("base", ["base", "base"], 32) + mapper = HealpixGridMapper("base", ["base1", "base2"], 32) assert nearest_points[0][0]["index"] == mapper.unmap((lat,), (lon,)) assert eccodes_lat - tol <= lat assert lat <= eccodes_lat + tol diff --git a/tests/test_healpix_nested_grid.py b/tests/test_healpix_nested_grid.py index 8d2108521..225b16206 100644 --- a/tests/test_healpix_nested_grid.py +++ b/tests/test_healpix_nested_grid.py @@ -3,12 +3,12 @@ import pandas as pd import pytest -from polytope.datacube.transformations.datacube_mappers.mapper_types.healpix_nested import ( +from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.healpix_nested import ( NestedHealpixGridMapper, ) -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestHealpixNestedGrid: diff --git a/tests/test_hull_slicer.py b/tests/test_hull_slicer.py index e733612f7..c05ca5814 100644 --- a/tests/test_hull_slicer.py +++ b/tests/test_hull_slicer.py @@ -2,15 +2,15 @@ import pytest -import polytope.engine.hullslicer -from polytope import ConvexPolytope -from polytope.datacube.backends.mock import MockDatacube -from polytope.utility.profiling import benchmark +from polytope_feature import ConvexPolytope +from polytope_feature.datacube.backends.mock import MockDatacube +from polytope_feature.engine.hullslicer import HullSlicer, slice +from polytope_feature.utility.profiling import benchmark class TestHullSlicer: def setup_method(self, method): - self.slicer = polytope.engine.hullslicer.HullSlicer() + self.slicer = HullSlicer() def construct_nd_cube(self, dimension, lower=-1, upper=1): axes = [str(chr(97 + ax)) for ax in range(dimension)] @@ -20,9 +20,9 @@ def construct_nd_cube(self, dimension, lower=-1, upper=1): def test_3D(self): p3 = self.construct_nd_cube(3) print(p3) - p2 = polytope.engine.hullslicer.slice(p3, "c", 0.5, 2) + p2 = slice(p3, "c", 0.5, 2) print(p2) - p1 = polytope.engine.hullslicer.slice(p2, "b", 0.5, 1) + p1 = slice(p2, "b", 0.5, 1) print(p1) @pytest.mark.skip(reason="This is too slow.") @@ -30,7 +30,7 @@ def test_4D(self): p = self.construct_nd_cube(4) print(p) while len(p.axes()) > 1: - p = polytope.engine.hullslicer.slice(p, p._axes[-1], 0.5, -1) + p = slice(p, p._axes[-1], 0.5, -1) print(p) @pytest.mark.skip(reason="This is too slow.") @@ -38,22 +38,22 @@ def test_ND(self): with benchmark("4D"): p = self.construct_nd_cube(4) while len(p.axes()) > 1: - p = polytope.engine.hullslicer.slice(p, p._axes[-1], 0.5, -1) + p = slice(p, p._axes[-1], 0.5, -1) with benchmark("5D"): p = self.construct_nd_cube(5) while len(p.axes()) > 1: - p = polytope.engine.hullslicer.slice(p, p._axes[-1], 0.5, -1) + p = slice(p, p._axes[-1], 0.5, -1) with benchmark("6D"): p = self.construct_nd_cube(6) while len(p.axes()) > 1: - p = polytope.engine.hullslicer.slice(p, p._axes[-1], 0.5, -1) + p = slice(p, p._axes[-1], 0.5, -1) with benchmark("7D"): p = self.construct_nd_cube(7) while len(p.axes()) > 1: - p = polytope.engine.hullslicer.slice(p, p._axes[-1], 0.5, -1) + p = slice(p, p._axes[-1], 0.5, -1) # QHull is not performant above 7D as per its documentation # with benchmark("8D"): diff --git a/tests/test_hullslicer_engine.py b/tests/test_hullslicer_engine.py index 148025323..198b96b25 100644 --- a/tests/test_hullslicer_engine.py +++ b/tests/test_hullslicer_engine.py @@ -1,11 +1,11 @@ import numpy as np import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.datacube.tensor_index_tree import TensorIndexTree -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope -from polytope.shapes import Box +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope +from polytope_feature.shapes import Box class TestSlicerComponents: diff --git a/tests/test_incomplete_tree_fdb.py b/tests/test_incomplete_tree_fdb.py index b863dac2a..2fbfcaf28 100644 --- a/tests/test_incomplete_tree_fdb.py +++ b/tests/test_incomplete_tree_fdb.py @@ -2,9 +2,9 @@ import pytest from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestRegularGrid: diff --git a/tests/test_local_grid_cyclic.py b/tests/test_local_grid_cyclic.py index b30f0c2cf..376f1e4a5 100644 --- a/tests/test_local_grid_cyclic.py +++ b/tests/test_local_grid_cyclic.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Point, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Point, Select class TestSlicingFDBDatacube: @@ -26,6 +26,7 @@ def setup_method(self, method): "resolution": [80, 80], "axes": ["latitude", "longitude"], "local": [-40, 40, -20, 60], + "axis_reversed": {"latitude": True, "longitude": False}, } ], }, diff --git a/tests/test_local_regular_grid.py b/tests/test_local_regular_grid.py index eee0525db..023c2dbdc 100644 --- a/tests/test_local_regular_grid.py +++ b/tests/test_local_regular_grid.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Point, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Point, Select class TestSlicingFDBDatacube: @@ -26,6 +26,7 @@ def setup_method(self, method): "resolution": [80, 80], "axes": ["latitude", "longitude"], "local": [-40, 40, -20, 60], + "axis_reversed": {"latitude": True, "longitude": False}, } ], }, diff --git a/tests/test_local_swiss_grid.py b/tests/test_local_swiss_grid.py index 29001f7ad..34019e54f 100644 --- a/tests/test_local_swiss_grid.py +++ b/tests/test_local_swiss_grid.py @@ -4,9 +4,9 @@ import pytest from eccodes import codes_grib_find_nearest, codes_grib_new_from_file -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingFDBDatacube: diff --git a/tests/test_mappers.py b/tests/test_mappers.py index fb4783a33..3a2cb4fb4 100644 --- a/tests/test_mappers.py +++ b/tests/test_mappers.py @@ -1,4 +1,4 @@ -from polytope.datacube.transformations.datacube_mappers.mapper_types.octahedral import ( +from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.octahedral import ( OctahedralGridMapper, ) diff --git a/tests/test_merge_cyclic_octahedral.py b/tests/test_merge_cyclic_octahedral.py index c44483a06..0997c806c 100644 --- a/tests/test_merge_cyclic_octahedral.py +++ b/tests/test_merge_cyclic_octahedral.py @@ -2,9 +2,9 @@ import pytest import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select, Span class TestMultipleTransformations: diff --git a/tests/test_merge_octahedral_one_axis.py b/tests/test_merge_octahedral_one_axis.py index 86e466769..e62e0ca99 100644 --- a/tests/test_merge_octahedral_one_axis.py +++ b/tests/test_merge_octahedral_one_axis.py @@ -2,9 +2,9 @@ from earthkit import data from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingMultipleTransformationsOneAxis: diff --git a/tests/test_merge_transformation.py b/tests/test_merge_transformation.py index 61c3284ae..5d2311c35 100644 --- a/tests/test_merge_transformation.py +++ b/tests/test_merge_transformation.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestMergeTransformation: diff --git a/tests/test_multiple_param_fdb.py b/tests/test_multiple_param_fdb.py index b12f11443..11285af84 100644 --- a/tests/test_multiple_param_fdb.py +++ b/tests/test_multiple_param_fdb.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingFDBDatacube: diff --git a/tests/test_octahedral_grid.py b/tests/test_octahedral_grid.py index 959f7ca64..abcdc543d 100644 --- a/tests/test_octahedral_grid.py +++ b/tests/test_octahedral_grid.py @@ -2,9 +2,9 @@ from earthkit import data from helper_functions import download_test_data, find_nearest_latlon -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestOctahedralGrid: diff --git a/tests/test_point_nearest.py b/tests/test_point_nearest.py index 75edf041b..b9fdc4bed 100644 --- a/tests/test_point_nearest.py +++ b/tests/test_point_nearest.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Point, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Point, Select class TestSlicingFDBDatacube: diff --git a/tests/test_point_shape.py b/tests/test_point_shape.py index 7b6d4c643..d4d6eb98f 100644 --- a/tests/test_point_shape.py +++ b/tests/test_point_shape.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Point, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Point, Select class TestSlicing3DXarrayDatacube: diff --git a/tests/test_profiling_requesttree.py b/tests/test_profiling_requesttree.py index 6bd6afac2..670da7881 100644 --- a/tests/test_profiling_requesttree.py +++ b/tests/test_profiling_requesttree.py @@ -3,10 +3,10 @@ import pytest import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestProfiling: diff --git a/tests/test_reduced_ll_grid.py b/tests/test_reduced_ll_grid.py index d554e528e..b0a3535c4 100644 --- a/tests/test_reduced_ll_grid.py +++ b/tests/test_reduced_ll_grid.py @@ -5,9 +5,9 @@ from eccodes import codes_grib_find_nearest, codes_grib_new_from_file from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestReducedLatLonGrid: diff --git a/tests/test_regular_grid.py b/tests/test_regular_grid.py index 45e2803df..4fbb13856 100644 --- a/tests/test_regular_grid.py +++ b/tests/test_regular_grid.py @@ -2,9 +2,9 @@ import pytest from helper_functions import download_test_data, find_nearest_latlon -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Disk, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Disk, Select # import geopandas as gpd # import matplotlib.pyplot as plt @@ -25,7 +25,13 @@ def setup_method(self, method): { "axis_name": "values", "transformations": [ - {"name": "mapper", "type": "regular", "resolution": 30, "axes": ["latitude", "longitude"]} + { + "name": "mapper", + "type": "regular", + "resolution": 30, + "axes": ["latitude", "longitude"], + "axis_reversed": {"latitude": True, "longitude": False}, + } ], }, {"axis_name": "latitude", "transformations": [{"name": "reverse", "is_reverse": True}]}, @@ -85,7 +91,7 @@ def test_regular_grid(self): assert len(result.leaves[1].values) == 3 assert len(result.leaves[2].values) == 1 - from polytope.datacube.transformations.datacube_mappers.mapper_types.regular import ( + from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.regular import ( RegularGridMapper, ) @@ -108,7 +114,7 @@ def test_regular_grid(self): eccodes_value = nearest_points[121][0]["value"] eccodes_lats.append(eccodes_lat) - mapper = RegularGridMapper("base", ["base", "base"], 30) + mapper = RegularGridMapper("base", ["base1", "base2"], 30) assert nearest_points[121][0]["index"] == mapper.unmap((lat,), (lon,)) assert eccodes_lat - tol <= lat diff --git a/tests/test_request_tree.py b/tests/test_request_tree.py index ddd0463e4..038599724 100644 --- a/tests/test_request_tree.py +++ b/tests/test_request_tree.py @@ -1,7 +1,7 @@ from sortedcontainers import SortedList -from polytope.datacube.datacube_axis import IntDatacubeAxis -from polytope.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.datacube.datacube_axis import IntDatacubeAxis +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree class TestIndexTree: diff --git a/tests/test_request_trees_after_slicing.py b/tests/test_request_trees_after_slicing.py index 3e7bf6dfb..2aa28b4a7 100644 --- a/tests/test_request_trees_after_slicing.py +++ b/tests/test_request_trees_after_slicing.py @@ -1,11 +1,11 @@ import numpy as np import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.datacube.datacube_axis import IntDatacubeAxis -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope -from polytope.shapes import Box +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.datacube.datacube_axis import IntDatacubeAxis +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope +from polytope_feature.shapes import Box class TestIndexTreesAfterSlicing: diff --git a/tests/test_reverse_transformation.py b/tests/test_reverse_transformation.py index aa4b27fe1..f1d9b24ed 100644 --- a/tests/test_reverse_transformation.py +++ b/tests/test_reverse_transformation.py @@ -1,9 +1,9 @@ import numpy as np import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestSlicingReverseTransformation: diff --git a/tests/test_shape_labels.py b/tests/test_shape_labels.py index b2108c8e4..e5e4619d4 100644 --- a/tests/test_shape_labels.py +++ b/tests/test_shape_labels.py @@ -2,10 +2,10 @@ import pandas as pd import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicing3DXarrayDatacube: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index ee17e6b22..3013be3f0 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -3,9 +3,9 @@ import pytest import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import All, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import All, Select, Span class TestSlicing3DXarrayDatacube: diff --git a/tests/test_slice_date_range_fdb.py b/tests/test_slice_date_range_fdb.py index 80d5c96e1..dae81cb22 100644 --- a/tests/test_slice_date_range_fdb.py +++ b/tests/test_slice_date_range_fdb.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Disk, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Disk, Select, Span class TestSlicingFDBDatacube: diff --git a/tests/test_slice_date_range_fdb_v2.py b/tests/test_slice_date_range_fdb_v2.py index c75a2ca7d..fcacf6b7c 100644 --- a/tests/test_slice_date_range_fdb_v2.py +++ b/tests/test_slice_date_range_fdb_v2.py @@ -2,9 +2,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select, Span class TestSlicingFDBDatacube: diff --git a/tests/test_slice_fdb_box.py b/tests/test_slice_fdb_box.py index aa65edf7e..f9daa128e 100644 --- a/tests/test_slice_fdb_box.py +++ b/tests/test_slice_fdb_box.py @@ -3,10 +3,10 @@ import pandas as pd import pytest -from polytope.datacube.tree_encoding import decode_tree, encode_tree -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import All, Box, Select +from polytope_feature.datacube.tree_encoding import decode_tree, encode_tree +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import All, Box, Select class TestSlicingFDBDatacube: diff --git a/tests/test_slicer_engine.py b/tests/test_slicer_engine.py index 29bdf5f09..289eeab6b 100644 --- a/tests/test_slicer_engine.py +++ b/tests/test_slicer_engine.py @@ -1,11 +1,11 @@ import numpy as np import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.datacube.tensor_index_tree import TensorIndexTree -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope -from polytope.shapes import Box +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope +from polytope_feature.shapes import Box class TestSlicerComponents: diff --git a/tests/test_slicer_era5.py b/tests/test_slicer_era5.py index 39a335c1a..4e7da9f48 100644 --- a/tests/test_slicer_era5.py +++ b/tests/test_slicer_era5.py @@ -3,9 +3,9 @@ from earthkit import data from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingEra5Data: diff --git a/tests/test_slicer_xarray.py b/tests/test_slicer_xarray.py index 428345e39..b36cd051c 100644 --- a/tests/test_slicer_xarray.py +++ b/tests/test_slicer_xarray.py @@ -2,9 +2,9 @@ import pandas as pd import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select, Span +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select, Span class TestXarraySlicing: diff --git a/tests/test_slicing_unsliceable_axis.py b/tests/test_slicing_unsliceable_axis.py index d021291d2..286252065 100644 --- a/tests/test_slicing_unsliceable_axis.py +++ b/tests/test_slicing_unsliceable_axis.py @@ -3,10 +3,10 @@ import pytest import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select -from polytope.utility.exceptions import UnsliceableShapeError +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select +from polytope_feature.utility.exceptions import UnsliceableShapeError class TestSlicingUnsliceableAxis: diff --git a/tests/test_slicing_xarray_3D.py b/tests/test_slicing_xarray_3D.py index cbffeccae..06df3ec6b 100644 --- a/tests/test_slicing_xarray_3D.py +++ b/tests/test_slicing_xarray_3D.py @@ -5,11 +5,11 @@ import pandas as pd import xarray as xr -from polytope.datacube.backends.xarray import XArrayDatacube -from polytope.datacube.tensor_index_tree import TensorIndexTree -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import ( +from polytope_feature.datacube.backends.xarray import XArrayDatacube +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import ( Box, ConvexPolytope, Disk, diff --git a/tests/test_slicing_xarray_4D.py b/tests/test_slicing_xarray_4D.py index c8b3abd5e..9345e8db5 100644 --- a/tests/test_slicing_xarray_4D.py +++ b/tests/test_slicing_xarray_4D.py @@ -3,10 +3,10 @@ import pytest import xarray as xr -from polytope.datacube.tensor_index_tree import TensorIndexTree -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import ( +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import ( Box, Disk, Ellipsoid, @@ -17,7 +17,10 @@ Span, Union, ) -from polytope.utility.exceptions import AxisOverdefinedError, AxisUnderdefinedError +from polytope_feature.utility.exceptions import ( + AxisOverdefinedError, + AxisUnderdefinedError, +) class TestSlicing4DXarrayDatacube: diff --git a/tests/test_snapping.py b/tests/test_snapping.py index bdb365ce5..529f1d69a 100644 --- a/tests/test_snapping.py +++ b/tests/test_snapping.py @@ -1,9 +1,9 @@ import numpy as np import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestSlicing3DXarrayDatacube: diff --git a/tests/test_snapping_real_data.py b/tests/test_snapping_real_data.py index c2bcc9f02..f8c350e43 100644 --- a/tests/test_snapping_real_data.py +++ b/tests/test_snapping_real_data.py @@ -6,9 +6,9 @@ from earthkit import data from helper_functions import download_test_data -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select class TestSlicingEra5Data: diff --git a/tests/test_tree_protobuf.py b/tests/test_tree_protobuf.py index a88633ea5..7f2e56f23 100644 --- a/tests/test_tree_protobuf.py +++ b/tests/test_tree_protobuf.py @@ -1,4 +1,4 @@ -import polytope.datacube.index_tree_pb2 as pb2 +import polytope_feature.datacube.index_tree_pb2 as pb2 class TestTreeProtobuf: diff --git a/tests/test_tree_protobuf_encoding.py b/tests/test_tree_protobuf_encoding.py index 7497453d4..b177cbe2b 100644 --- a/tests/test_tree_protobuf_encoding.py +++ b/tests/test_tree_protobuf_encoding.py @@ -1,15 +1,15 @@ import pytest -from polytope.datacube.backends.mock import MockDatacube -from polytope.datacube.datacube_axis import ( +from polytope_feature.datacube.backends.mock import MockDatacube +from polytope_feature.datacube.datacube_axis import ( FloatDatacubeAxis, IntDatacubeAxis, PandasTimedeltaDatacubeAxis, PandasTimestampDatacubeAxis, UnsliceableDatacubeAxis, ) -from polytope.datacube.tensor_index_tree import TensorIndexTree -from polytope.datacube.tree_encoding import decode_tree, encode_tree +from polytope_feature.datacube.tensor_index_tree import TensorIndexTree +from polytope_feature.datacube.tree_encoding import decode_tree, encode_tree class TestEncoder: @@ -49,8 +49,8 @@ def setup_method(self): def test_encoding(self): import pygribjump as gj - from polytope.engine.hullslicer import HullSlicer - from polytope.polytope import Polytope + from polytope_feature.engine.hullslicer import HullSlicer + from polytope_feature.polytope import Polytope self.options = { "pre_path": {"class": "od", "expver": "0001", "levtype": "sfc", "stream": "oper"}, diff --git a/tests/test_tree_protobuf_encoding_fdb.py b/tests/test_tree_protobuf_encoding_fdb.py index 7cef1070e..2e288f0d6 100644 --- a/tests/test_tree_protobuf_encoding_fdb.py +++ b/tests/test_tree_protobuf_encoding_fdb.py @@ -1,7 +1,7 @@ import pandas as pd import pytest -from polytope.datacube.tree_encoding import decode_tree, encode_tree +from polytope_feature.datacube.tree_encoding import decode_tree, encode_tree class TestEncoder: @@ -12,9 +12,9 @@ def setup_method(self): def test_encoding(self): import pygribjump as gj - from polytope.engine.hullslicer import HullSlicer - from polytope.polytope import Polytope, Request - from polytope.shapes import Box, Select + from polytope_feature.engine.hullslicer import HullSlicer + from polytope_feature.polytope import Polytope, Request + from polytope_feature.shapes import Box, Select request = Request( Select("step", [0]), diff --git a/tests/test_type_change_transformation.py b/tests/test_type_change_transformation.py index f74dd4744..09f800610 100644 --- a/tests/test_type_change_transformation.py +++ b/tests/test_type_change_transformation.py @@ -1,9 +1,9 @@ import numpy as np import xarray as xr -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Select +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Select class TestTypeChangeTransformation: diff --git a/tests/test_union_gj.py b/tests/test_union_gj.py index 30f22fc54..9182fc360 100644 --- a/tests/test_union_gj.py +++ b/tests/test_union_gj.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Select, Span, Union +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Select, Span, Union class TestSlicingFDBDatacube: diff --git a/tests/test_union_point_box.py b/tests/test_union_point_box.py index 7b7d1152d..ba280bc02 100644 --- a/tests/test_union_point_box.py +++ b/tests/test_union_point_box.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from polytope.engine.hullslicer import HullSlicer -from polytope.polytope import Polytope, Request -from polytope.shapes import Box, Point, Select, Union +from polytope_feature.engine.hullslicer import HullSlicer +from polytope_feature.polytope import Polytope, Request +from polytope_feature.shapes import Box, Point, Select, Union class TestSlicingFDBDatacube: diff --git a/tox.ini b/tox.ini index 36b7ba462..495b19988 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ exclude = .* extend-ignore = E203,W503 per-file-ignores = */__init__.py: F401,F403 - polytope/datacube/index_tree_pb2.py: E501 + polytope_feature/datacube/index_tree_pb2.py: E501 [isort] profile=black skip_glob=.* \ No newline at end of file