polytope-python 2.0.1__tar.gz → 2.0.2__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 (271) hide show
  1. {polytope_python-2.0.1/polytope_python.egg-info → polytope_python-2.0.2}/PKG-INFO +1 -1
  2. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/_version.py +1 -1
  3. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_type_change/datacube_type_change.py +25 -0
  4. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/quadtree_slicer.py +9 -2
  5. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/polytope.py +25 -4
  6. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/shapes.py +20 -12
  7. {polytope_python-2.0.1 → polytope_python-2.0.2/polytope_python.egg-info}/PKG-INFO +1 -1
  8. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_python.egg-info/SOURCES.txt +2 -0
  9. polytope_python-2.0.2/rust/src/distance.rs +33 -0
  10. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/lib.rs +1 -0
  11. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/quadtree_mod.rs +44 -0
  12. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_lambert_lam_grid_unstructured_fdb.py +96 -1
  13. polytope_python-2.0.2/tests/test_shapes_volume.py +21 -0
  14. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_type_change_transformation.py +10 -0
  15. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/ci-config.yml +0 -0
  16. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/ci-hpc-config.yml +0 -0
  17. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/workflows/cd.yml +0 -0
  18. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/workflows/downstream-ci.yml +0 -0
  19. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/workflows/label-public-pr.yml +0 -0
  20. {polytope_python-2.0.1 → polytope_python-2.0.2}/.github/workflows/test-pypi.yml +0 -0
  21. {polytope_python-2.0.1 → polytope_python-2.0.2}/.gitignore +0 -0
  22. {polytope_python-2.0.1 → polytope_python-2.0.2}/.pre-commit-config.yaml +0 -0
  23. {polytope_python-2.0.1 → polytope_python-2.0.2}/.readthedocs.yaml +0 -0
  24. {polytope_python-2.0.1 → polytope_python-2.0.2}/ACKNOWLEDGEMENTS.rst +0 -0
  25. {polytope_python-2.0.1 → polytope_python-2.0.2}/CONTRIBUTING.rst +0 -0
  26. {polytope_python-2.0.1 → polytope_python-2.0.2}/LICENSE +0 -0
  27. {polytope_python-2.0.1 → polytope_python-2.0.2}/Makefile +0 -0
  28. {polytope_python-2.0.1 → polytope_python-2.0.2}/README.md +0 -0
  29. {polytope_python-2.0.1 → polytope_python-2.0.2}/codecov.yml +0 -0
  30. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/API.md +0 -0
  31. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/Axis_types.md +0 -0
  32. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/Datacube.md +0 -0
  33. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/Overview.md +0 -0
  34. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/Slicer.md +0 -0
  35. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/images/Polytope_APIs_3.png +0 -0
  36. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/images/polytope_components_5.png +0 -0
  37. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/images/slicing_process.png +0 -0
  38. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Developer_Guide/shapes.md +0 -0
  39. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Overview/Overview.md +0 -0
  40. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Overview/Polytope_at_ECMWF.md +0 -0
  41. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Overview/images_overview/ecmwf_datacube.png +0 -0
  42. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/Overview/images_overview/ecmwf_polytope.png +0 -0
  43. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/User_Guide/Building_Features.md +0 -0
  44. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/User_Guide/Example.md +0 -0
  45. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/User_Guide/Getting_started.md +0 -0
  46. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/User_Guide/Overview.md +0 -0
  47. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Algorithm/User_Guide/images_users/shipping_route.png +0 -0
  48. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Data_Portfolio.md +0 -0
  49. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Design_doc.md +0 -0
  50. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_boundingbox_example.ipynb +0 -0
  51. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_country_example.ipynb +0 -0
  52. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_polygon_example.ipynb +0 -0
  53. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_timeseries_example.ipynb +0 -0
  54. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_trajectory_example.ipynb +0 -0
  55. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/OpenData/od_vertical_profile_example.ipynb +0 -0
  56. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/boundingbox_example.ipynb +0 -0
  57. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/country_example.ipynb +0 -0
  58. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/examples.md +0 -0
  59. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/polygon_example.ipynb +0 -0
  60. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/timeseries_example.ipynb +0 -0
  61. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/trajectory_example.ipynb +0 -0
  62. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Examples/vertical_profile_example.ipynb +0 -0
  63. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/boundingbox.md +0 -0
  64. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/feature.md +0 -0
  65. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/polygon.md +0 -0
  66. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/timeseries.md +0 -0
  67. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/trajectory.md +0 -0
  68. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Features/vertical_profile.md +0 -0
  69. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Installation.md +0 -0
  70. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Overview.md +0 -0
  71. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/Service/Quick_Start.md +0 -0
  72. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/extra.css +0 -0
  73. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/flight_path.png +0 -0
  74. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/greece.png +0 -0
  75. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/logo.gif +0 -0
  76. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/polytope_feature.png +0 -0
  77. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/polytope_logo_new_animated_AdobeExpress_3.gif +0 -0
  78. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/timeseries.png +0 -0
  79. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/timeseries_example.png +0 -0
  80. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/images/timeseries_qs.png +0 -0
  81. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/index.md +0 -0
  82. {polytope_python-2.0.1 → polytope_python-2.0.2}/docs/requirements.txt +0 -0
  83. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/3D_shipping_route.py +0 -0
  84. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/3D_shipping_route_wave_model.py +0 -0
  85. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/4D_flight_path.py +0 -0
  86. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/country_slicing.py +0 -0
  87. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/cyclic_route_around_earth.py +0 -0
  88. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/EMODnet_HA_WindFarms_pg_20220324.shp +0 -0
  89. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/EMODnet_HA_WindFarms_pg_20220324.shx +0 -0
  90. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/Shipping-Lanes-v1.shp +0 -0
  91. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/Shipping-Lanes-v1.shx +0 -0
  92. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/World_Countries__Generalized_.shp +0 -0
  93. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/World_Countries__Generalized_.shx +0 -0
  94. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/earth_image.jpg +0 -0
  95. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/map_earth_4k.jpg +0 -0
  96. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/mars_req_9km_wind.req +0 -0
  97. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/mars_req_levels.req +0 -0
  98. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/mars_req_timeseries.req +0 -0
  99. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/output4.grib +0 -0
  100. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/output4.req +0 -0
  101. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/output8.grib +0 -0
  102. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/output8.req +0 -0
  103. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/temp_model_levels.grib +0 -0
  104. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/timeseries_t2m.grib +0 -0
  105. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/data/winds.grib +0 -0
  106. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/healpix_grid_box_example.py +0 -0
  107. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/octahedral_grid_box_example.py +0 -0
  108. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/octahedral_grid_country_example.py +0 -0
  109. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/plotting_country_data.py +0 -0
  110. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/read_me_example.py +0 -0
  111. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/requirements_examples.txt +0 -0
  112. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/slicing_all_ecmwf_countries.py +0 -0
  113. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/timeseries_example.py +0 -0
  114. {polytope_python-2.0.1 → polytope_python-2.0.2}/examples/wind_farms.py +0 -0
  115. {polytope_python-2.0.1 → polytope_python-2.0.2}/mkdocs.yml +0 -0
  116. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/fdb_performance.py +0 -0
  117. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/fdb_performance_3D.py +0 -0
  118. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/fdb_scalability_plot.py +0 -0
  119. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/fdb_slice_many_numbers_timeseries.py +0 -0
  120. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/performance_many_num_steps.py +0 -0
  121. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/plotting_scalability.py +0 -0
  122. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/scalability_test.py +0 -0
  123. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance/scalability_test_2.py +0 -0
  124. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance_unstructured/octahedral_vs_unstructured_slicing.py +0 -0
  125. {polytope_python-2.0.1 → polytope_python-2.0.2}/performance_unstructured/plot_structured_vs_unstructured_slicing.py +0 -0
  126. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/__init__.py +0 -0
  127. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/__init__.py +0 -0
  128. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/__init__.py +0 -0
  129. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/catalogue_helper.py +0 -0
  130. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/datacube.py +0 -0
  131. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/fdb.py +0 -0
  132. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/mock.py +0 -0
  133. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/backends/xarray.py +0 -0
  134. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/datacube_axis.py +0 -0
  135. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/index_tree.proto +0 -0
  136. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/index_tree_pb2.py +0 -0
  137. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/quadtree/quad_tree.py +0 -0
  138. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/quadtree/quadtree_additional_operations.py +0 -0
  139. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/tensor_index_tree.py +0 -0
  140. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/__init__.py +0 -0
  141. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_cyclic/__init__.py +0 -0
  142. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_cyclic/datacube_cyclic.py +0 -0
  143. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/__init__.py +0 -0
  144. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/datacube_mappers.py +0 -0
  145. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/__init__.py +0 -0
  146. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix.py +0 -0
  147. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/healpix_nested.py +0 -0
  148. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/irregular.py +0 -0
  149. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/irregular_mapper_types/__init__.py +0 -0
  150. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/irregular_mapper_types/icon.py +0 -0
  151. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/irregular_mapper_types/lambert_conformal.py +0 -0
  152. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/irregular_mapper_types/unstructured.py +0 -0
  153. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/local_regular.py +0 -0
  154. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/octahedral.py +0 -0
  155. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_gaussian.py +0 -0
  156. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/reduced_ll.py +0 -0
  157. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_mappers/mapper_types/regular.py +0 -0
  158. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_merger/__init__.py +0 -0
  159. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_merger/datacube_merger.py +0 -0
  160. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_reverse/__init__.py +0 -0
  161. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_reverse/datacube_reverse.py +0 -0
  162. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_transformations.py +0 -0
  163. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/transformations/datacube_type_change/__init__.py +0 -0
  164. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/datacube/tree_encoding.py +0 -0
  165. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/__init__.py +0 -0
  166. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/engine.py +0 -0
  167. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/hullslicer.py +0 -0
  168. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/optimised_point_in_polygon_slicer.py +0 -0
  169. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/optimised_quadtree_slicer.py +0 -0
  170. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/point_in_polygon_slicer.py +0 -0
  171. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/engine/slicing_tools.py +0 -0
  172. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/options.py +0 -0
  173. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/__init__.py +0 -0
  174. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/combinatorics.py +0 -0
  175. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/engine_tools.py +0 -0
  176. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/exceptions.py +0 -0
  177. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/geometry.py +0 -0
  178. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/list_tools.py +0 -0
  179. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_feature/utility/profiling.py +0 -0
  180. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_python.egg-info/dependency_links.txt +0 -0
  181. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_python.egg-info/requires.txt +0 -0
  182. {polytope_python-2.0.1 → polytope_python-2.0.2}/polytope_python.egg-info/top_level.txt +0 -0
  183. {polytope_python-2.0.1 → polytope_python-2.0.2}/pyproject.toml +0 -0
  184. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/Cargo.toml +0 -0
  185. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/healpix_nested.rs +0 -0
  186. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/lambert_conformal.rs +0 -0
  187. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/list_tools.rs +0 -0
  188. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/octahedral.rs +0 -0
  189. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/point_in_polygon.rs +0 -0
  190. {polytope_python-2.0.1 → polytope_python-2.0.2}/rust/src/slicing_tools.rs +0 -0
  191. {polytope_python-2.0.1 → polytope_python-2.0.2}/setup.cfg +0 -0
  192. {polytope_python-2.0.1 → polytope_python-2.0.2}/setup.py +0 -0
  193. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/conftest.py +0 -0
  194. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/fdb_data/schema +0 -0
  195. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/helper_functions.py +0 -0
  196. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/profiled_quadtree.profile +0 -0
  197. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/quadtree_slicer_profiler.py +0 -0
  198. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_axis_mappers.py +0 -0
  199. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_bad_request_error.py +0 -0
  200. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_combinatorics.py +0 -0
  201. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_axis_over_negative_vals.py +0 -0
  202. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_axis_slicer_not_0.py +0 -0
  203. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_axis_slicing.py +0 -0
  204. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_nearest.py +0 -0
  205. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_simple.py +0 -0
  206. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_cyclic_snapping.py +0 -0
  207. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_datacube_axes_init.py +0 -0
  208. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_datacube_mock.py +0 -0
  209. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_datacube_xarray.py +0 -0
  210. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_date_time_unmerged.py +0 -0
  211. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_ecmwf_oper_data_fdb.py +0 -0
  212. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_engine_slicer.py +0 -0
  213. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_fdb_datacube.py +0 -0
  214. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_fdb_unmap_tree.py +0 -0
  215. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_float_type.py +0 -0
  216. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_healpix_mapper.py +0 -0
  217. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_healpix_nested_grid.py +0 -0
  218. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_hull_slicer.py +0 -0
  219. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_hullslicer_engine.py +0 -0
  220. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_icon_grid_unstructured.py +0 -0
  221. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_icon_grid_unstructured_fdb.py +0 -0
  222. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_incomplete_tree_fdb.py +0 -0
  223. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_lambert_lam_grid_unstructured_fdb_optimised_quadtree.py +0 -0
  224. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_local_grid_cyclic.py +0 -0
  225. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_local_regular_grid.py +0 -0
  226. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_local_swiss_grid.py +0 -0
  227. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_mappers.py +0 -0
  228. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_merge_cyclic_octahedral.py +0 -0
  229. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_merge_octahedral_one_axis.py +0 -0
  230. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_merge_transformation.py +0 -0
  231. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_multiple_param_fdb.py +0 -0
  232. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_octahedral_grid.py +0 -0
  233. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_orca_irregular_grid.py +0 -0
  234. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_orca_irregular_grid_optimised_point_in_polygon.py +0 -0
  235. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_orca_irregular_grid_point_in_polygon.py +0 -0
  236. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_override_md5_hash_options.py +0 -0
  237. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_point_nearest.py +0 -0
  238. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_point_shape.py +0 -0
  239. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_point_union.py +0 -0
  240. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_polytope_extract.py +0 -0
  241. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_polytope_extract_fdb.py +0 -0
  242. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_profiling_requesttree.py +0 -0
  243. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_quad_tree.py +0 -0
  244. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_quadtree_edge_cases.py +0 -0
  245. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_quadtree_indices.py +0 -0
  246. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_quadtree_optimisation.py +0 -0
  247. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_reduced_ll_grid.py +0 -0
  248. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_regular_grid.py +0 -0
  249. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_regular_reduced_grid.py +0 -0
  250. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_request_tree.py +0 -0
  251. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_request_trees_after_slicing.py +0 -0
  252. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_reverse_transformation.py +0 -0
  253. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_shapes.py +0 -0
  254. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slice_date_range_fdb.py +0 -0
  255. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slice_date_range_fdb_v2.py +0 -0
  256. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slice_fdb_box.py +0 -0
  257. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicer_engine.py +0 -0
  258. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicer_era5.py +0 -0
  259. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicer_xarray.py +0 -0
  260. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicing_unsliceable_axis.py +0 -0
  261. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicing_xarray_3D.py +0 -0
  262. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_slicing_xarray_4D.py +0 -0
  263. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_snapping.py +0 -0
  264. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_snapping_real_data.py +0 -0
  265. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_tree_protobuf.py +0 -0
  266. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_tree_protobuf_encoding.py +0 -0
  267. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_tree_protobuf_encoding_fdb.py +0 -0
  268. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_union_gj.py +0 -0
  269. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_union_point_box.py +0 -0
  270. {polytope_python-2.0.1 → polytope_python-2.0.2}/tests/test_wave_spectra_data.py +0 -0
  271. {polytope_python-2.0.1 → polytope_python-2.0.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polytope-python
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Author-email: "European Centre for Medium-Range Weather Forecasts (ECMWF)" <software.support@ecmwf.int>
6
6
  Maintainer-email: James Hawkes <James.Hawkes@ecmwf.int>, Mathilde Leuridan <Mathilde.Leuridan@ecmwf.int>
@@ -1,2 +1,2 @@
1
1
  # Do not change! Do not track in version control!
2
- __version__ = "2.0.1"
2
+ __version__ = "2.0.2"
@@ -78,6 +78,30 @@ class TypeChangeStrToInt(DatacubeAxisTypeChange):
78
78
  return tuple(values)
79
79
 
80
80
 
81
+ class TypeChangeStrToFloat(DatacubeAxisTypeChange):
82
+ def __init__(self, axis_name, new_type):
83
+ self.axis_name = axis_name
84
+ self._new_type = new_type
85
+
86
+ def transform_type(self, value):
87
+ try:
88
+ return float(value)
89
+ except ValueError:
90
+ return None
91
+
92
+ def make_str(self, value):
93
+ values = []
94
+ for val in value:
95
+ int_val = int(val)
96
+ if val == int_val:
97
+ # we return a str of the integer value
98
+ values.append(str(int_val))
99
+ else:
100
+ # we return a str of the float value
101
+ values.append(str(val))
102
+ return tuple(values)
103
+
104
+
81
105
  class TypeChangeStrToTimestamp(DatacubeAxisTypeChange):
82
106
  def __init__(self, axis_name, new_type):
83
107
  self.axis_name = axis_name
@@ -195,6 +219,7 @@ _type_to_datacube_type_change_lookup = {
195
219
  "int": "TypeChangeStrToInt",
196
220
  "date": "TypeChangeStrToTimestamp",
197
221
  "time": "TypeChangeStrToTimedelta",
222
+ "float": "TypeChangeStrToFloat",
198
223
  "subhourly_step_compact": "TypeChangeSubHourlyTimeStepsCompact",
199
224
  "subhourly_step": "TypeChangeSubHourlyTimeSteps",
200
225
  }
@@ -26,9 +26,16 @@ class QuadTreeSlicer(Engine):
26
26
 
27
27
  def extract_single(self, datacube, polytope):
28
28
  # extract a single polygon
29
+ # if need to find nearest points, then take alternative slicing method using quadtree to find nearest point
29
30
  if use_rust:
30
- polytope_points = [tuple(point) for point in polytope.points]
31
- polygon_points = self.quad_tree.query_polygon(self.points, 0, polytope_points)
31
+ if len(datacube.nearest_search) == 0:
32
+ polytope_points = [tuple(point) for point in polytope.points]
33
+ polygon_points = self.quad_tree.query_polygon(self.points, 0, polytope_points)
34
+ else:
35
+ nn_points = [tuple(pt) for pt in datacube.nearest_search[tuple(polytope.axes())]]
36
+ polygon_points = []
37
+ for nn_pt in nn_points:
38
+ polygon_points.append(self.quad_tree.nearest_neighbor(nn_pt, self.points))
32
39
  else:
33
40
  polygon_points = self.quad_tree.query_polygon(polytope)
34
41
  return polygon_points
@@ -10,7 +10,7 @@ from .engine.optimised_quadtree_slicer import OptimisedQuadTreeSlicer
10
10
  from .engine.point_in_polygon_slicer import PointInPolygonSlicer
11
11
  from .engine.quadtree_slicer import QuadTreeSlicer
12
12
  from .options import PolytopeOptions
13
- from .shapes import ConvexPolytope, Product
13
+ from .shapes import ConvexPolytope, Point, Product, Union
14
14
  from .utility.combinatorics import group, tensor_product
15
15
  from .utility.exceptions import AxisOverdefinedError
16
16
  from .utility.list_tools import unique
@@ -122,6 +122,7 @@ class Polytope:
122
122
 
123
123
  def slice(self, datacube, polytopes: List[ConvexPolytope]):
124
124
  """Low-level API which takes a polytope geometry object and uses it to slice the datacube"""
125
+
125
126
  self.find_compressed_axes(datacube, polytopes)
126
127
 
127
128
  self.remove_compressed_axis_in_union(polytopes)
@@ -176,17 +177,37 @@ class Polytope:
176
177
  slicer_type = self.engine_options[ax.name]
177
178
  return self.engines[slicer_type]
178
179
 
180
+ def switch_polytope_dim(self, request):
181
+ # If we see a 2-dim slicer on an axis
182
+ # then make sure that if the shape is a point, we set decompose_1D to False
183
+ for ax, slicer in self.engine_options.items():
184
+ if slicer == "quadtree":
185
+ for shp in request.shapes:
186
+ if ax in shp.axes() and isinstance(shp, Point):
187
+ shp.decompose_1D = False
188
+ elif isinstance(shp, Union):
189
+ for s in shp._shapes:
190
+ if ax in s.axes() and isinstance(s, Point):
191
+ s.decompose_1D = False
192
+
179
193
  def retrieve(self, request: Request, method="standard"):
180
194
  """Higher-level API which takes a request and uses it to slice the datacube"""
181
195
  logging.info("Starting request for %s ", self.context)
182
196
  self.datacube.check_branching_axes(request)
197
+ self.switch_polytope_dim(request)
183
198
  for polytope in request.polytopes():
184
199
  method = polytope.method
185
200
  if method == "nearest":
186
- if self.datacube.nearest_search.get(tuple(polytope.axes()), None) is None:
187
- self.datacube.nearest_search[tuple(polytope.axes())] = polytope.values
201
+ if polytope.is_flat:
202
+ if self.datacube.nearest_search.get(tuple(polytope.axes()), None) is None:
203
+ self.datacube.nearest_search[tuple(polytope.axes())] = polytope.values
204
+ else:
205
+ self.datacube.nearest_search[tuple(polytope.axes())].append(polytope.values[0])
188
206
  else:
189
- self.datacube.nearest_search[tuple(polytope.axes())].append(polytope.values[0])
207
+ if self.datacube.nearest_search.get(tuple(polytope.axes()), None) is None:
208
+ self.datacube.nearest_search[tuple(polytope.axes())] = polytope.points
209
+ else:
210
+ self.datacube.nearest_search[tuple(polytope.axes())].append(polytope.points[0])
190
211
  request_tree = self.slice(self.datacube, request.polytopes())
191
212
  logging.info("Created request tree for %s ", self.context)
192
213
  self.datacube.get(request_tree, self.context)
@@ -77,8 +77,12 @@ class Product(Shape):
77
77
  assert len(self._axes) == len(all_axes)
78
78
 
79
79
  self._polytopes = []
80
+ self.is_flat = True
80
81
  for poly in polytopes:
81
82
  self._polytopes.extend(poly.polytope())
83
+ for p in poly.polytope():
84
+ if len(p.axes()) > 1:
85
+ self.is_flat = False
82
86
 
83
87
  self.is_in_union = False
84
88
  self.method = method
@@ -128,6 +132,7 @@ class Point(Shape):
128
132
  self._axes = axes
129
133
  self.values = values
130
134
  self.method = method
135
+ self.decompose_1D = True
131
136
  assert len(values) == 1
132
137
 
133
138
  def axes(self):
@@ -137,11 +142,15 @@ class Point(Shape):
137
142
  # TODO: change this to use the Product instead and return a Product here of the two 1D selects
138
143
 
139
144
  polytopes = []
140
- for point in self.values:
141
- poly_to_mult = []
142
- for i in range(len(self._axes)):
143
- poly_to_mult.append(ConvexPolytope([self._axes[i]], [[point[i]]], self.method, is_orthogonal=True))
144
- polytopes.append(Product(*poly_to_mult, method=self.method, value=[point]))
145
+ if self.decompose_1D:
146
+ for point in self.values:
147
+ poly_to_mult = []
148
+ for i in range(len(self._axes)):
149
+ poly_to_mult.append(ConvexPolytope([self._axes[i]], [[point[i]]], self.method, is_orthogonal=True))
150
+ polytopes.append(Product(*poly_to_mult, method=self.method, value=[point]))
151
+ else:
152
+ for point in self.values:
153
+ polytopes.append(ConvexPolytope(self._axes, [point], self.method, is_orthogonal=True))
145
154
  self.polytopes = polytopes
146
155
 
147
156
  return self.polytopes
@@ -464,19 +473,18 @@ class Union(Shape):
464
473
  self._axes = axes
465
474
  for s in shapes:
466
475
  assert s.axes() == self.axes()
467
-
468
- self.polytopes = []
469
476
  self._shapes = shapes
470
477
 
471
- for s in shapes:
472
- for poly in s.polytope():
473
- poly.add_to_union()
474
- self.polytopes.append(poly)
475
-
476
478
  def axes(self):
477
479
  return self._axes
478
480
 
479
481
  def polytope(self):
482
+ self.polytopes = []
483
+
484
+ for s in self._shapes:
485
+ for poly in s.polytope():
486
+ poly.add_to_union()
487
+ self.polytopes.append(poly)
480
488
  return self.polytopes
481
489
 
482
490
  def __repr__(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polytope-python
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: Polytope datacube feature extraction library
5
5
  Author-email: "European Centre for Medium-Range Weather Forecasts (ECMWF)" <software.support@ecmwf.int>
6
6
  Maintainer-email: James Hawkes <James.Hawkes@ecmwf.int>, Mathilde Leuridan <Mathilde.Leuridan@ecmwf.int>
@@ -177,6 +177,7 @@ polytope_python.egg-info/dependency_links.txt
177
177
  polytope_python.egg-info/requires.txt
178
178
  polytope_python.egg-info/top_level.txt
179
179
  rust/Cargo.toml
180
+ rust/src/distance.rs
180
181
  rust/src/healpix_nested.rs
181
182
  rust/src/lambert_conformal.rs
182
183
  rust/src/lib.rs
@@ -246,6 +247,7 @@ tests/test_request_tree.py
246
247
  tests/test_request_trees_after_slicing.py
247
248
  tests/test_reverse_transformation.py
248
249
  tests/test_shapes.py
250
+ tests/test_shapes_volume.py
249
251
  tests/test_slice_date_range_fdb.py
250
252
  tests/test_slice_date_range_fdb_v2.py
251
253
  tests/test_slice_fdb_box.py
@@ -0,0 +1,33 @@
1
+ pub fn dist2(a: (f64, f64), b: (f64, f64)) -> f64 {
2
+ let dx = a.0 - b.0;
3
+ let dy = a.1 - b.1;
4
+ dx * dx + dy * dy
5
+ }
6
+
7
+ pub fn box_dist2(center: (f64, f64), size: (f64, f64), point: (f64, f64)) -> f64 {
8
+ let half_w = size.0 / 2.0;
9
+ let half_h = size.1 / 2.0;
10
+
11
+ let min_x = center.0 - half_w;
12
+ let max_x = center.0 + half_w;
13
+ let min_y = center.1 - half_h;
14
+ let max_y = center.1 + half_h;
15
+
16
+ let dx = if point.0 < min_x {
17
+ min_x - point.0
18
+ } else if point.0 > max_x {
19
+ point.0 - max_x
20
+ } else {
21
+ 0.0
22
+ };
23
+
24
+ let dy = if point.1 < min_y {
25
+ min_y - point.1
26
+ } else if point.1 > max_y {
27
+ point.1 - max_y
28
+ } else {
29
+ 0.0
30
+ };
31
+
32
+ dx * dx + dy * dy
33
+ }
@@ -3,6 +3,7 @@ pub mod lambert_conformal;
3
3
  pub mod list_tools;
4
4
  use pyo3::wrap_pyfunction;
5
5
 
6
+ pub mod distance;
6
7
  use crate::lambert_conformal::{get_latlons_oblate, get_latlons_sphere};
7
8
 
8
9
  pub mod healpix_nested;
@@ -9,6 +9,7 @@ use pyo3::exceptions::PyRuntimeError;
9
9
  // TODO: look at rust built in arena
10
10
 
11
11
  use crate::slicing_tools::{is_contained_in, slice_in_two};
12
+ use crate::distance::{dist2, box_dist2};
12
13
 
13
14
 
14
15
 
@@ -54,6 +55,16 @@ impl QuadTree {
54
55
  }
55
56
  }
56
57
 
58
+ fn nearest_neighbor(&self, query: (f64, f64), quadtree_points: Vec<(f64, f64)>) -> Option<usize> {
59
+ if self.nodes.is_empty() {
60
+ return None;
61
+ }
62
+ let mut best_idx = None;
63
+ let mut best_dist2 = f64::INFINITY;
64
+ self.nn_search(0, query, &mut best_idx, &mut best_dist2, &quadtree_points);
65
+ best_idx
66
+ }
67
+
57
68
  fn sizeof(&self) -> usize {
58
69
  let mut size = size_of::<Self>();
59
70
  let nodes_size: usize = self.nodes.len() * size_of::<QuadTreeNode>();
@@ -145,6 +156,39 @@ impl QuadTree {
145
156
  points.into_iter().map(|(x, y)| [x,y]).collect()
146
157
  }
147
158
 
159
+ fn nn_search(
160
+ &self,
161
+ node_idx: usize,
162
+ query: (f64, f64),
163
+ best_idx: &mut Option<usize>,
164
+ best_dist2: &mut f64,
165
+ quadtree_points: &Vec<(f64, f64)>
166
+ ) {
167
+ let node = &self.nodes[node_idx];
168
+
169
+ // if this node is farther than the current best, ignore
170
+ if box_dist2(node.center, node.size, query) > *best_dist2 {
171
+ return;
172
+ }
173
+
174
+ // compare distance of points inside leaf node
175
+ if let Some(point_indices) = &node.points {
176
+ for &pi in point_indices {
177
+ let p = quadtree_points[pi];
178
+ let d2 = dist2(p, query);
179
+ if d2 < *best_dist2 {
180
+ *best_dist2 = d2;
181
+ *best_idx = Some(pi);
182
+ }
183
+ }
184
+ return;
185
+ }
186
+ // else, recurse into children
187
+ for &child_idx in &node.children {
188
+ self.nn_search(child_idx, query, best_idx, best_dist2, &quadtree_points);
189
+ }
190
+ }
191
+
148
192
  fn convert_polygon(&self, points: Option<Vec<(f64, f64)>>) -> Option<Vec<[f64; 2]>> {
149
193
  points.map(|pts| pts.into_iter().map(|(x, y)| [x, y]).collect())
150
194
  }
@@ -6,7 +6,7 @@ import pytest
6
6
  from helper_functions import find_nearest_latlon
7
7
 
8
8
  from polytope_feature.polytope import Polytope, Request
9
- from polytope_feature.shapes import Box, Select
9
+ from polytope_feature.shapes import Box, Point, Select, Union
10
10
 
11
11
 
12
12
  class TestQuadTreeSlicer:
@@ -111,3 +111,98 @@ class TestQuadTreeSlicer:
111
111
  # plt.scatter(eccodes_lons, eccodes_lats, s=6, c="green")
112
112
  # plt.colorbar(label="Temperature")
113
113
  # plt.show()
114
+
115
+ @pytest.mark.fdb
116
+ def test_quad_tree_slicer_extract_point(self):
117
+ import pygribjump as gj
118
+
119
+ request = Request(
120
+ Select("date", [pd.Timestamp("20250221T0000")]),
121
+ Select("step", [0]),
122
+ Select("param", ["130"]),
123
+ Select("levtype", ["sfc"]),
124
+ Point(["latitude", "longitude"], [[44.25, 5.55]], method="nearest"),
125
+ )
126
+
127
+ self.fdbdatacube = gj.GribJump()
128
+
129
+ self.API = Polytope(
130
+ datacube=self.fdbdatacube,
131
+ options=self.options,
132
+ )
133
+
134
+ result = self.API.retrieve(request)
135
+ assert len(result.leaves) == 1
136
+ result.pprint()
137
+
138
+ lats = []
139
+ lons = []
140
+ eccodes_lats = []
141
+ eccodes_lons = []
142
+ tol = 1e-3
143
+ leaves = result.leaves
144
+ for i in range(len(leaves)):
145
+ cubepath = leaves[i].flatten()
146
+ lat = cubepath["latitude"][0]
147
+ lon = cubepath["longitude"][0]
148
+ lats.append(lat)
149
+ lons.append(lon)
150
+ nearest_points = find_nearest_latlon("tests/data/lambert_lam_one_message.grib", lat, lon)
151
+ eccodes_lat = nearest_points[0][0]["lat"]
152
+ eccodes_lon = nearest_points[0][0]["lon"]
153
+ eccodes_lats.append(eccodes_lat)
154
+ eccodes_lons.append(eccodes_lon)
155
+ assert eccodes_lat - tol <= lat
156
+ assert lat <= eccodes_lat + tol
157
+ assert eccodes_lon - tol <= lon
158
+ assert lon <= eccodes_lon + tol
159
+
160
+ @pytest.mark.fdb
161
+ def test_quad_tree_slicer_extract_point_union(self):
162
+ import pygribjump as gj
163
+
164
+ pt1 = Point(["latitude", "longitude"], [[44.25, 5.55]], method="nearest")
165
+ pt2 = Point(["latitude", "longitude"], [[43.75, 5.35]], method="nearest")
166
+
167
+ pt_union = Union(["latitude", "longitude"], pt1, pt2)
168
+
169
+ request = Request(
170
+ Select("date", [pd.Timestamp("20250221T0000")]),
171
+ Select("step", [0]),
172
+ Select("param", ["130"]),
173
+ Select("levtype", ["sfc"]),
174
+ pt_union,
175
+ )
176
+
177
+ self.fdbdatacube = gj.GribJump()
178
+
179
+ self.API = Polytope(
180
+ datacube=self.fdbdatacube,
181
+ options=self.options,
182
+ )
183
+
184
+ result = self.API.retrieve(request)
185
+ assert len(result.leaves) == 2
186
+ result.pprint()
187
+
188
+ lats = []
189
+ lons = []
190
+ eccodes_lats = []
191
+ eccodes_lons = []
192
+ tol = 1e-3
193
+ leaves = result.leaves
194
+ for i in range(len(leaves)):
195
+ cubepath = leaves[i].flatten()
196
+ lat = cubepath["latitude"][0]
197
+ lon = cubepath["longitude"][0]
198
+ lats.append(lat)
199
+ lons.append(lon)
200
+ nearest_points = find_nearest_latlon("tests/data/lambert_lam_one_message.grib", lat, lon)
201
+ eccodes_lat = nearest_points[0][0]["lat"]
202
+ eccodes_lon = nearest_points[0][0]["lon"]
203
+ eccodes_lats.append(eccodes_lat)
204
+ eccodes_lons.append(eccodes_lon)
205
+ assert eccodes_lat - tol <= lat
206
+ assert lat <= eccodes_lat + tol
207
+ assert eccodes_lon - tol <= lon
208
+ assert lon <= eccodes_lon + tol
@@ -0,0 +1,21 @@
1
+ from polytope_feature.shapes import ConvexPolytope, Point, Product
2
+
3
+
4
+ class TestShapeDimension:
5
+ def setup_method(self, method):
6
+ pass
7
+
8
+ def test_point_dimension(self):
9
+ point_1D = Point(["lat", "lon"], [[1, 1]])
10
+
11
+ for shp in point_1D.polytope():
12
+ assert isinstance(shp, Product)
13
+ for polytope in shp._polytopes:
14
+ assert len(polytope.axes()) == 1
15
+
16
+ point_2D = Point(["lat", "lon"], [[1, 1]])
17
+ point_2D.decompose_1D = False
18
+
19
+ for shp in point_2D.polytope():
20
+ assert isinstance(shp, ConvexPolytope)
21
+ assert len(shp.axes()) == 2
@@ -3,6 +3,7 @@ import pandas as pd
3
3
  import xarray as xr
4
4
 
5
5
  from polytope_feature.datacube.transformations.datacube_type_change.datacube_type_change import (
6
+ TypeChangeStrToFloat,
6
7
  TypeChangeSubHourlyTimeSteps,
7
8
  TypeChangeSubHourlyTimeStepsCompact,
8
9
  )
@@ -33,6 +34,15 @@ class TestIntTypeChangeTransformation:
33
34
  result.pprint()
34
35
  assert result.leaves[0].flatten()["step"] == (0,)
35
36
 
37
+ def test_float_type_change_axis(self):
38
+ type_change_transform = TypeChangeStrToFloat("step", "float")
39
+
40
+ assert type_change_transform.transform_type("0.5") == 0.5
41
+ assert type_change_transform.transform_type("0") == 0.0
42
+
43
+ assert type_change_transform.make_str([0.1]) == ("0.1",)
44
+ assert type_change_transform.make_str([0.0]) == ("0",)
45
+
36
46
  def test_subhourly_step_type_change_axis(self):
37
47
  type_change_transform = TypeChangeSubHourlyTimeSteps("step", "subhourly_step")
38
48
 
File without changes