polytope-python 1.0.38__tar.gz → 1.0.40__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. {polytope_python-1.0.38/polytope_python.egg-info → polytope_python-1.0.40}/PKG-INFO +1 -1
  2. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py +1 -1
  3. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +8 -18
  4. polytope_python-1.0.40/polytope_feature/utility/__init__.py +0 -0
  5. polytope_python-1.0.40/polytope_feature/version.py +1 -0
  6. {polytope_python-1.0.38 → polytope_python-1.0.40/polytope_python.egg-info}/PKG-INFO +1 -1
  7. polytope_python-1.0.40/tests/test_healpix_nested_grid.py +262 -0
  8. polytope_python-1.0.38/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -5
  9. polytope_python-1.0.38/polytope_feature/version.py +0 -1
  10. polytope_python-1.0.38/tests/test_healpix_nested_grid.py +0 -182
  11. {polytope_python-1.0.38 → polytope_python-1.0.40}/LICENSE +0 -0
  12. {polytope_python-1.0.38 → polytope_python-1.0.40}/MANIFEST.in +0 -0
  13. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/__init__.py +0 -0
  14. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/__init__.py +0 -0
  15. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/backends/__init__.py +0 -0
  16. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/backends/datacube.py +0 -0
  17. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/backends/fdb.py +0 -0
  18. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/backends/mock.py +0 -0
  19. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/backends/xarray.py +0 -0
  20. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/datacube_axis.py +0 -0
  21. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/index_tree_pb2.py +0 -0
  22. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/tensor_index_tree.py +0 -0
  23. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/__init__.py +0 -0
  24. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_cyclic/__init__.py +0 -0
  25. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
  26. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/__init__.py +0 -0
  27. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py +0 -0
  28. {polytope_python-1.0.38/polytope_feature/utility → polytope_python-1.0.40/polytope_feature/datacube/transformations/datacube_mappers/mapper_types}/__init__.py +0 -0
  29. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +0 -0
  30. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +0 -0
  31. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_gaussian.py +0 -0
  32. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +0 -0
  33. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py +0 -0
  34. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_merger/__init__.py +0 -0
  35. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py +0 -0
  36. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_reverse/__init__.py +0 -0
  37. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
  38. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_transformations.py +0 -0
  39. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_type_change/__init__.py +0 -0
  40. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py +0 -0
  41. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/datacube/tree_encoding.py +0 -0
  42. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/engine/__init__.py +0 -0
  43. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/engine/engine.py +0 -0
  44. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/engine/hullslicer.py +0 -0
  45. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/options.py +0 -0
  46. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/polytope.py +0 -0
  47. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/shapes.py +0 -0
  48. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/utility/combinatorics.py +0 -0
  49. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/utility/exceptions.py +0 -0
  50. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/utility/geometry.py +0 -0
  51. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/utility/list_tools.py +0 -0
  52. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_feature/utility/profiling.py +0 -0
  53. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_python.egg-info/SOURCES.txt +0 -0
  54. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_python.egg-info/dependency_links.txt +0 -0
  55. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_python.egg-info/not-zip-safe +0 -0
  56. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_python.egg-info/requires.txt +0 -0
  57. {polytope_python-1.0.38 → polytope_python-1.0.40}/polytope_python.egg-info/top_level.txt +0 -0
  58. {polytope_python-1.0.38 → polytope_python-1.0.40}/pyproject.toml +0 -0
  59. {polytope_python-1.0.38 → polytope_python-1.0.40}/requirements.txt +0 -0
  60. {polytope_python-1.0.38 → polytope_python-1.0.40}/setup.cfg +0 -0
  61. {polytope_python-1.0.38 → polytope_python-1.0.40}/setup.py +0 -0
  62. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_axis_mappers.py +0 -0
  63. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_bad_request_error.py +0 -0
  64. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_combinatorics.py +0 -0
  65. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_axis_over_negative_vals.py +0 -0
  66. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_axis_slicer_not_0.py +0 -0
  67. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_axis_slicing.py +0 -0
  68. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_nearest.py +0 -0
  69. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_simple.py +0 -0
  70. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_cyclic_snapping.py +0 -0
  71. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_datacube_axes_init.py +0 -0
  72. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_datacube_mock.py +0 -0
  73. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_datacube_xarray.py +0 -0
  74. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_date_time_unmerged.py +0 -0
  75. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_ecmwf_oper_data_fdb.py +0 -0
  76. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_engine_slicer.py +0 -0
  77. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_fdb_datacube.py +0 -0
  78. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_fdb_unmap_tree.py +0 -0
  79. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_float_type.py +0 -0
  80. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_healpix_mapper.py +0 -0
  81. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_hull_slicer.py +0 -0
  82. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_hullslicer_engine.py +0 -0
  83. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_incomplete_tree_fdb.py +0 -0
  84. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_local_grid_cyclic.py +0 -0
  85. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_local_regular_grid.py +0 -0
  86. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_local_swiss_grid.py +0 -0
  87. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_mappers.py +0 -0
  88. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_merge_cyclic_octahedral.py +0 -0
  89. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_merge_octahedral_one_axis.py +0 -0
  90. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_merge_transformation.py +0 -0
  91. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_multiple_param_fdb.py +0 -0
  92. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_octahedral_grid.py +0 -0
  93. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_override_md5_hash_options.py +0 -0
  94. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_point_nearest.py +0 -0
  95. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_point_shape.py +0 -0
  96. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_point_union.py +0 -0
  97. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_profiling_requesttree.py +0 -0
  98. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_reduced_ll_grid.py +0 -0
  99. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_regular_grid.py +0 -0
  100. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_regular_reduced_grid.py +0 -0
  101. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_request_tree.py +0 -0
  102. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_request_trees_after_slicing.py +0 -0
  103. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_reverse_transformation.py +0 -0
  104. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_shapes.py +0 -0
  105. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slice_date_range_fdb.py +0 -0
  106. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slice_date_range_fdb_v2.py +0 -0
  107. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slice_fdb_box.py +0 -0
  108. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicer_engine.py +0 -0
  109. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicer_era5.py +0 -0
  110. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicer_xarray.py +0 -0
  111. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicing_unsliceable_axis.py +0 -0
  112. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicing_xarray_3D.py +0 -0
  113. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_slicing_xarray_4D.py +0 -0
  114. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_snapping.py +0 -0
  115. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_snapping_real_data.py +0 -0
  116. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_tree_protobuf.py +0 -0
  117. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_tree_protobuf_encoding.py +0 -0
  118. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_tree_protobuf_encoding_fdb.py +0 -0
  119. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_type_change_transformation.py +0 -0
  120. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_union_gj.py +0 -0
  121. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_union_point_box.py +0 -0
  122. {polytope_python-1.0.38 → polytope_python-1.0.40}/tests/test_wave_spectra_data.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polytope-python
3
- Version: 1.0.38
3
+ Version: 1.0.40
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -101,7 +101,7 @@ class HealpixGridMapper(DatacubeMapper):
101
101
  return idx
102
102
  for i in range(3 * self._resolution, 4 * self._resolution - 1):
103
103
  if i != first_idx:
104
- idx += 4 * (4 * self._resolution - 1 - i + 1)
104
+ idx += 4 * (4 * self._resolution - 1 - i)
105
105
  else:
106
106
  idx += second_idx
107
107
  return idx
@@ -13,11 +13,9 @@ class NestedHealpixGridMapper(DatacubeMapper):
13
13
  self._first_axis_vals = self.first_axis_vals()
14
14
  self.compressed_grid_axes = [self._mapped_axes[1]]
15
15
  self.Nside = self._resolution
16
- self._cached_longitudes = {}
17
16
  self.k = int(math.log2(self.Nside))
18
17
  self.Npix = 12 * self.Nside * self.Nside
19
18
  self.Ncap = (self.Nside * (self.Nside - 1)) << 1
20
- self._healpix_longitudes = {}
21
19
  if md5_hash is not None:
22
20
  self.md5_hash = md5_hash
23
21
  else:
@@ -59,9 +57,7 @@ class NestedHealpixGridMapper(DatacubeMapper):
59
57
  return values
60
58
 
61
59
  def second_axis_vals_from_idx(self, first_val_idx):
62
- if first_val_idx not in self._healpix_longitudes:
63
- self._healpix_longitudes[first_val_idx] = self.HEALPix_longitudes(first_val_idx)
64
- values = self._healpix_longitudes[first_val_idx]
60
+ values = self.HEALPix_longitudes(first_val_idx)
65
61
  return values
66
62
 
67
63
  def HEALPix_nj(self, i):
@@ -77,19 +73,13 @@ class NestedHealpixGridMapper(DatacubeMapper):
77
73
  return self.HEALPix_nj(ni - 1 - i)
78
74
 
79
75
  def HEALPix_longitudes(self, i):
80
- if i in self._cached_longitudes:
81
- return self._cached_longitudes[i]
82
- else:
83
- Nj = self.HEALPix_nj(i)
84
- step = 360.0 / Nj
85
- start = (
86
- step / 2.0
87
- if i < self._resolution or 3 * self._resolution - 1 < i or (i + self._resolution) % 2
88
- else 0.0
89
- )
76
+ Nj = self.HEALPix_nj(i)
77
+ step = 360.0 / Nj
78
+ start = (
79
+ step / 2.0 if i < self._resolution or 3 * self._resolution - 1 < i or (i + self._resolution) % 2 else 0.0
80
+ )
90
81
 
91
- longitudes = [start + n * step for n in range(Nj)]
92
- self._cached_longitudes[i] = longitudes
82
+ longitudes = [start + n * step for n in range(Nj)]
93
83
  return longitudes
94
84
 
95
85
  def map_second_axis(self, first_val, lower, upper):
@@ -113,7 +103,7 @@ class NestedHealpixGridMapper(DatacubeMapper):
113
103
  return idx
114
104
  for i in range(3 * self._resolution, 4 * self._resolution - 1):
115
105
  if i != first_idx:
116
- idx += 4 * (4 * self._resolution - 1 - i + 1)
106
+ idx += 4 * (4 * self._resolution - 1 - i)
117
107
  else:
118
108
  idx += second_idx
119
109
  return idx
@@ -0,0 +1 @@
1
+ __version__ = "1.0.40"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polytope-python
3
- Version: 1.0.38
3
+ Version: 1.0.40
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Home-page: https://github.com/ecmwf/polytope
6
6
  Author: ECMWF
@@ -0,0 +1,262 @@
1
+ import pandas as pd
2
+ import pytest
3
+ from earthkit import data
4
+ from helper_functions import download_test_data, find_nearest_latlon
5
+
6
+ from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.healpix_nested import (
7
+ NestedHealpixGridMapper,
8
+ )
9
+ from polytope_feature.engine.hullslicer import HullSlicer
10
+ from polytope_feature.polytope import Polytope, Request
11
+ from polytope_feature.shapes import Box, Select
12
+
13
+
14
+ class TestHealpixNestedGrid:
15
+ def setup_method(self, method):
16
+ nexus_url = "https://get.ecmwf.int/test-data/polytope/test-data/healpix_nested.grib"
17
+ download_test_data(nexus_url, "healpix_nested.grib")
18
+
19
+ ds = data.from_source("file", "./tests/data/healpix_nested.grib")[3]
20
+ self.latlon_array = ds.to_xarray(engine="cfgrib").isel(step=0).isel(time=0).isel(heightAboveGround=0).t2m
21
+ self.options = {
22
+ "axis_config": [
23
+ {
24
+ "axis_name": "date",
25
+ "transformations": [{"name": "merge", "other_axis": "time", "linkers": ["T", "00"]}],
26
+ },
27
+ {
28
+ "axis_name": "values",
29
+ "transformations": [
30
+ {
31
+ "name": "mapper",
32
+ "type": "healpix_nested",
33
+ "resolution": 128,
34
+ "axes": ["latitude", "longitude"],
35
+ }
36
+ ],
37
+ },
38
+ {"axis_name": "latitude", "transformations": [{"name": "reverse", "is_reverse": True}]},
39
+ {"axis_name": "longitude", "transformations": [{"name": "cyclic", "range": [0, 360]}]},
40
+ ],
41
+ "pre_path": {"class": "d1", "expver": "0001", "levtype": "sfc", "stream": "clte"},
42
+ "compressed_axes_config": [
43
+ "longitude",
44
+ "latitude",
45
+ ],
46
+ "alternative_axes": [
47
+ {
48
+ "axis_name": "class",
49
+ "values": [
50
+ "d1",
51
+ ],
52
+ },
53
+ {
54
+ "axis_name": "activity",
55
+ "values": [
56
+ "ScenarioMIP",
57
+ ],
58
+ },
59
+ {
60
+ "axis_name": "dataset",
61
+ "values": ["climate-dt"],
62
+ },
63
+ {
64
+ "axis_name": "date",
65
+ "values": ["20200102"],
66
+ },
67
+ {
68
+ "axis_name": "time",
69
+ "values": ["0100"],
70
+ },
71
+ {
72
+ "axis_name": "experiment",
73
+ "values": ["SSP3-7.0"],
74
+ },
75
+ {
76
+ "axis_name": "expver",
77
+ "values": ["0001"],
78
+ },
79
+ {
80
+ "axis_name": "generation",
81
+ "values": ["1"],
82
+ },
83
+ {
84
+ "axis_name": "levtype",
85
+ "values": ["sfc"],
86
+ },
87
+ {
88
+ "axis_name": "model",
89
+ "values": ["IFS-NEMO"],
90
+ },
91
+ {
92
+ "axis_name": "param",
93
+ "values": ["167"],
94
+ },
95
+ {
96
+ "axis_name": "realization",
97
+ "values": ["1"],
98
+ },
99
+ {
100
+ "axis_name": "resolution",
101
+ "values": ["standard"],
102
+ },
103
+ {
104
+ "axis_name": "stream",
105
+ "values": ["clte"],
106
+ },
107
+ {
108
+ "axis_name": "type",
109
+ "values": ["fc"],
110
+ },
111
+ ],
112
+ }
113
+ self.slicer = HullSlicer()
114
+ self.API = Polytope(
115
+ datacube=self.latlon_array,
116
+ engine=self.slicer,
117
+ options=self.options,
118
+ )
119
+
120
+ @pytest.mark.internet
121
+ def test_healpix_nested_grid_equator(self):
122
+ request = Request(
123
+ Select("valid_time", [pd.Timestamp("20200102T010000")]),
124
+ Select("time", [pd.Timestamp("20200102T010000")]),
125
+ Select("step", [0]),
126
+ Select("heightAboveGround", [2]),
127
+ Box(["latitude", "longitude"], [0, 0], [2, 2]),
128
+ )
129
+ result = self.API.retrieve(request)
130
+ result.pprint()
131
+ assert len(result.leaves) == 7
132
+ tot_leaves = 0
133
+ for leaf in result.leaves:
134
+ tot_leaves += len(leaf.result[1])
135
+ assert tot_leaves == 21
136
+
137
+ lats = []
138
+ lons = []
139
+ eccodes_lats = []
140
+ eccodes_lons = []
141
+ tol = 1e-8
142
+ for i, leaf in enumerate(result.leaves[:]):
143
+ cubepath = leaf.flatten()
144
+ lat = cubepath["latitude"]
145
+ lons_ = cubepath["longitude"]
146
+ for i, lon in enumerate(lons_):
147
+ lon = [
148
+ lon,
149
+ ]
150
+ lats.append(lat)
151
+ lons.append(lon)
152
+ nearest_points = find_nearest_latlon("./tests/data/healpix_nested.grib", lat[0], lon[0])
153
+ eccodes_lat = nearest_points[0][0]["lat"]
154
+ eccodes_lon = nearest_points[0][0]["lon"]
155
+ eccodes_result = nearest_points[3][0]["value"]
156
+ eccodes_lats.append(eccodes_lat)
157
+ eccodes_lons.append(eccodes_lon)
158
+
159
+ mapper = NestedHealpixGridMapper("values", ["latitude", "longitude"], 128)
160
+ assert nearest_points[0][0]["index"] == mapper.unmap(lat, lon)[0]
161
+ assert eccodes_lat - tol <= lat[0]
162
+ assert lat[0] <= eccodes_lat + tol
163
+ assert eccodes_lon - tol <= lon[0]
164
+ assert lon[0] <= eccodes_lon + tol
165
+ assert leaf.result[1][i] - 1e-4 <= eccodes_result <= leaf.result[1][i] + 1e-4
166
+ assert len(eccodes_lats) == 21
167
+
168
+ @pytest.mark.internet
169
+ def test_healpix_nested_grid_south_pole(self):
170
+ request = Request(
171
+ Select("valid_time", [pd.Timestamp("20200102T010000")]),
172
+ Select("time", [pd.Timestamp("20200102T010000")]),
173
+ Select("step", [0]),
174
+ Select("heightAboveGround", [2]),
175
+ Box(["latitude", "longitude"], [-87, 0], [-85, 10]),
176
+ )
177
+ result = self.API.retrieve(request)
178
+ result.pprint()
179
+ assert len(result.leaves) == 5
180
+ tot_leaves = 0
181
+ for leaf in result.leaves:
182
+ tot_leaves += len(leaf.result[1])
183
+ assert tot_leaves == 5
184
+
185
+ lats = []
186
+ lons = []
187
+ eccodes_lats = []
188
+ eccodes_lons = []
189
+ tol = 1e-8
190
+ for i, leaf in enumerate(result.leaves[:]):
191
+ cubepath = leaf.flatten()
192
+ lat = cubepath["latitude"]
193
+ lons_ = cubepath["longitude"]
194
+ for i, lon in enumerate(lons_):
195
+ lon = [
196
+ lon,
197
+ ]
198
+ lats.append(lat)
199
+ lons.append(lon)
200
+ nearest_points = find_nearest_latlon("./tests/data/healpix_nested.grib", lat[0], lon[0])
201
+ eccodes_lat = nearest_points[0][0]["lat"]
202
+ eccodes_lon = nearest_points[0][0]["lon"]
203
+ eccodes_result = nearest_points[3][0]["value"]
204
+ eccodes_lats.append(eccodes_lat)
205
+ eccodes_lons.append(eccodes_lon)
206
+
207
+ mapper = NestedHealpixGridMapper("values", ["latitude", "longitude"], 128)
208
+ assert nearest_points[0][0]["index"] == mapper.unmap(lat, lon)[0]
209
+ assert eccodes_lat - tol <= lat[0]
210
+ assert lat[0] <= eccodes_lat + tol
211
+ assert eccodes_lon - tol <= lon[0]
212
+ assert lon[0] <= eccodes_lon + tol
213
+ assert leaf.result[1][i] - 1e-4 <= eccodes_result <= leaf.result[1][i] + 1e-4
214
+ assert len(eccodes_lats) == 5
215
+
216
+ @pytest.mark.internet
217
+ def test_healpix_nested_grid_north_pole(self):
218
+ request = Request(
219
+ Select("valid_time", [pd.Timestamp("20200102T010000")]),
220
+ Select("time", [pd.Timestamp("20200102T010000")]),
221
+ Select("step", [0]),
222
+ Select("heightAboveGround", [2]),
223
+ Box(["latitude", "longitude"], [83, 0], [86, 10]),
224
+ )
225
+ result = self.API.retrieve(request)
226
+ result.pprint()
227
+ assert len(result.leaves) == 9
228
+ tot_leaves = 0
229
+ for leaf in result.leaves:
230
+ tot_leaves += len(leaf.result[1])
231
+ assert tot_leaves == 15
232
+
233
+ lats = []
234
+ lons = []
235
+ eccodes_lats = []
236
+ eccodes_lons = []
237
+ tol = 1e-8
238
+ for i, leaf in enumerate(result.leaves[:]):
239
+ cubepath = leaf.flatten()
240
+ lat = cubepath["latitude"]
241
+ lons_ = cubepath["longitude"]
242
+ for i, lon in enumerate(lons_):
243
+ lon = [
244
+ lon,
245
+ ]
246
+ lats.append(lat)
247
+ lons.append(lon)
248
+ nearest_points = find_nearest_latlon("./tests/data/healpix_nested.grib", lat[0], lon[0])
249
+ eccodes_lat = nearest_points[0][0]["lat"]
250
+ eccodes_lon = nearest_points[0][0]["lon"]
251
+ eccodes_result = nearest_points[3][0]["value"]
252
+ eccodes_lats.append(eccodes_lat)
253
+ eccodes_lons.append(eccodes_lon)
254
+
255
+ mapper = NestedHealpixGridMapper("values", ["latitude", "longitude"], 128)
256
+ assert nearest_points[0][0]["index"] == mapper.unmap(lat, lon)[0]
257
+ assert eccodes_lat - tol <= lat[0]
258
+ assert lat[0] <= eccodes_lat + tol
259
+ assert eccodes_lon - tol <= lon[0]
260
+ assert lon[0] <= eccodes_lon + tol
261
+ assert leaf.result[1][i] - 1e-4 <= eccodes_result <= leaf.result[1][i] + 1e-4
262
+ assert len(eccodes_lats) == 15
@@ -1,5 +0,0 @@
1
- from .healpix import *
2
- from .local_regular import *
3
- from .octahedral import *
4
- from .reduced_ll import *
5
- from .regular import *
@@ -1 +0,0 @@
1
- __version__ = "1.0.38"
@@ -1,182 +0,0 @@
1
- # import geopandas as gpd
2
- # import matplotlib.pyplot as plt
3
- import pandas as pd
4
- import pytest
5
-
6
- from polytope_feature.datacube.transformations.datacube_mappers.mapper_types.healpix_nested import (
7
- NestedHealpixGridMapper,
8
- )
9
- from polytope_feature.engine.hullslicer import HullSlicer
10
- from polytope_feature.polytope import Polytope, Request
11
- from polytope_feature.shapes import Box, Select
12
-
13
-
14
- class TestHealpixNestedGrid:
15
- def setup_method(self, method):
16
- self.options = {
17
- "axis_config": [
18
- {
19
- "axis_name": "date",
20
- "transformations": [{"name": "merge", "other_axis": "time", "linkers": ["T", "00"]}],
21
- },
22
- {
23
- "axis_name": "values",
24
- "transformations": [
25
- {
26
- "name": "mapper",
27
- "type": "healpix_nested",
28
- "resolution": 128,
29
- "axes": ["latitude", "longitude"],
30
- }
31
- ],
32
- },
33
- {"axis_name": "latitude", "transformations": [{"name": "reverse", "is_reverse": True}]},
34
- {"axis_name": "longitude", "transformations": [{"name": "cyclic", "range": [0, 360]}]},
35
- ],
36
- "pre_path": {"class": "d1", "expver": "0001", "levtype": "sfc", "stream": "clte"},
37
- "compressed_axes_config": [
38
- "longitude",
39
- "latitude",
40
- ],
41
- "alternative_axes": [
42
- {
43
- "axis_name": "class",
44
- "values": [
45
- "d1",
46
- ],
47
- },
48
- {
49
- "axis_name": "activity",
50
- "values": [
51
- "ScenarioMIP",
52
- ],
53
- },
54
- {
55
- "axis_name": "dataset",
56
- "values": ["climate-dt"],
57
- },
58
- {
59
- "axis_name": "date",
60
- "values": ["20200102"],
61
- },
62
- {
63
- "axis_name": "time",
64
- "values": ["0100"],
65
- },
66
- {
67
- "axis_name": "experiment",
68
- "values": ["SSP3-7.0"],
69
- },
70
- {
71
- "axis_name": "expver",
72
- "values": ["0001"],
73
- },
74
- {
75
- "axis_name": "generation",
76
- "values": ["1"],
77
- },
78
- {
79
- "axis_name": "levtype",
80
- "values": ["sfc"],
81
- },
82
- {
83
- "axis_name": "model",
84
- "values": ["IFS-NEMO"],
85
- },
86
- {
87
- "axis_name": "param",
88
- "values": ["167"],
89
- },
90
- {
91
- "axis_name": "realization",
92
- "values": ["1"],
93
- },
94
- {
95
- "axis_name": "resolution",
96
- "values": ["standard"],
97
- },
98
- {
99
- "axis_name": "stream",
100
- "values": ["clte"],
101
- },
102
- {
103
- "axis_name": "type",
104
- "values": ["fc"],
105
- },
106
- ],
107
- }
108
-
109
- @pytest.mark.internet
110
- @pytest.mark.fdb
111
- @pytest.mark.skip(reason="different fdb schema for climate dt")
112
- def test_healpix_nested_grid(self):
113
- import pygribjump as gj
114
-
115
- request = Request(
116
- Select("activity", ["ScenarioMIP"]),
117
- Select("class", ["d1"]),
118
- Select("dataset", ["climate-dt"]),
119
- Select("date", [pd.Timestamp("20200102T010000")]),
120
- Select("experiment", ["SSP3-7.0"]),
121
- Select("expver", ["0001"]),
122
- Select("generation", ["1"]),
123
- Select("levtype", ["sfc"]),
124
- Select("model", ["IFS-NEMO"]),
125
- Select("param", ["167"]),
126
- Select("realization", ["1"]),
127
- Select("resolution", ["standard"]),
128
- Select("stream", ["clte"]),
129
- Select("type", ["fc"]),
130
- Box(["latitude", "longitude"], [0, 0], [2, 2]),
131
- )
132
-
133
- self.fdbdatacube = gj.GribJump()
134
- self.slicer = HullSlicer()
135
- self.API = Polytope(
136
- datacube=self.fdbdatacube,
137
- engine=self.slicer,
138
- options=self.options,
139
- )
140
-
141
- result = self.API.retrieve(request)
142
- result.pprint()
143
- assert len(result.leaves) == 21
144
-
145
- from helper_functions import find_nearest_latlon
146
-
147
- lats = []
148
- lons = []
149
- eccodes_lats = []
150
- eccodes_lons = []
151
- tol = 1e-8
152
- for i, leaf in enumerate(result.leaves[:]):
153
- cubepath = leaf.flatten()
154
- result_tree = leaf.result[0]
155
- lat = cubepath["latitude"]
156
- lon = cubepath["longitude"]
157
- lats.append(lat)
158
- lons.append(lon)
159
- nearest_points = find_nearest_latlon("./tests/data/healpix_nested.grib", lat[0], lon[0])
160
- eccodes_lat = nearest_points[0][0]["lat"]
161
- eccodes_lon = nearest_points[0][0]["lon"]
162
- eccodes_result = nearest_points[3][0]["value"]
163
- eccodes_lats.append(eccodes_lat)
164
- eccodes_lons.append(eccodes_lon)
165
-
166
- mapper = NestedHealpixGridMapper("base", ["base", "base"], 128)
167
- assert nearest_points[0][0]["index"] == mapper.unmap(lat, lon)
168
- assert eccodes_lat - tol <= lat[0]
169
- assert lat[0] <= eccodes_lat + tol
170
- assert eccodes_lon - tol <= lon[0]
171
- assert lon[0] <= eccodes_lon + tol
172
- assert eccodes_result == result_tree
173
- assert len(eccodes_lats) == 21
174
-
175
- # worldmap = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
176
- # fig, ax = plt.subplots(figsize=(12, 6))
177
- # worldmap.plot(color="darkgrey", ax=ax)
178
-
179
- # plt.scatter(lons, lats, s=18, c="red", cmap="YlOrRd")
180
- # plt.scatter(eccodes_lons, eccodes_lats, s=6, c="green")
181
- # plt.colorbar(label="Temperature")
182
- # plt.show()