cloudanalyzer 0.4.0__tar.gz → 0.5.0__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 (249) hide show
  1. {cloudanalyzer-0.4.0/cloudanalyzer.egg-info → cloudanalyzer-0.5.0}/PKG-INFO +13 -2
  2. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/__init__.py +1 -1
  3. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/batch.py +9 -1
  4. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/benchmark.py +263 -1
  5. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/__init__.py +12 -0
  6. cloudanalyzer-0.5.0/ca/core/bag_ingest.py +323 -0
  7. cloudanalyzer-0.5.0/ca/core/cameras.py +306 -0
  8. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/check_triage.py +74 -2
  9. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/checks.py +712 -30
  10. cloudanalyzer-0.5.0/ca/core/gate.py +133 -0
  11. cloudanalyzer-0.5.0/ca/core/gs_renderer.py +205 -0
  12. cloudanalyzer-0.5.0/ca/core/image_evaluate.py +472 -0
  13. cloudanalyzer-0.5.0/ca/core/map_evaluate.py +672 -0
  14. cloudanalyzer-0.5.0/ca/core/plane_consistency.py +214 -0
  15. cloudanalyzer-0.5.0/ca/core/rendered_evaluate.py +287 -0
  16. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/slam_run.py +156 -8
  17. cloudanalyzer-0.5.0/ca/core/uncertainty_evaluate.py +131 -0
  18. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/__init__.py +10 -0
  19. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/common.py +21 -0
  20. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/extract_all.py +10 -0
  21. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/pointcloud.py +7 -0
  22. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/stream_decode.py +10 -0
  23. cloudanalyzer-0.5.0/ca/experiments/bag_ingest/trajectory.py +7 -0
  24. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/kiss_icp_driver.py +2 -1
  25. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/info.py +8 -8
  26. cloudanalyzer-0.5.0/ca/io.py +440 -0
  27. cloudanalyzer-0.5.0/ca/leaderboard.py +373 -0
  28. cloudanalyzer-0.5.0/ca/mapeval_benchmark.py +150 -0
  29. cloudanalyzer-0.5.0/ca/mapeval_parity.py +778 -0
  30. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/object_eval.py +7 -2
  31. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/pr_comment.py +60 -10
  32. cloudanalyzer-0.5.0/ca/protocol.py +261 -0
  33. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/report.py +612 -10
  34. cloudanalyzer-0.5.0/ca/report_paths.py +42 -0
  35. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/run_evaluate.py +16 -0
  36. cloudanalyzer-0.5.0/ca/testing/__init__.py +5 -0
  37. cloudanalyzer-0.5.0/ca/testing/conformance.py +236 -0
  38. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/trajectory.py +417 -14
  39. cloudanalyzer-0.5.0/ca/visualization.py +174 -0
  40. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0/cloudanalyzer.egg-info}/PKG-INFO +13 -2
  41. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer.egg-info/SOURCES.txt +40 -0
  42. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer.egg-info/requires.txt +15 -1
  43. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer_cli/main.py +965 -56
  44. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/pyproject.toml +15 -1
  45. cloudanalyzer-0.5.0/tests/test_bag_ingest.py +329 -0
  46. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_benchmark.py +113 -0
  47. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_bundle.py +19 -15
  48. cloudanalyzer-0.5.0/tests/test_cameras.py +96 -0
  49. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_check_suite.py +85 -0
  50. cloudanalyzer-0.5.0/tests/test_check_suite_image.py +258 -0
  51. cloudanalyzer-0.5.0/tests/test_check_suite_rendered.py +300 -0
  52. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_cli.py +106 -0
  53. cloudanalyzer-0.5.0/tests/test_docs_golden_path.py +59 -0
  54. cloudanalyzer-0.5.0/tests/test_driver_conformance.py +102 -0
  55. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_geometry.py +9 -1
  56. cloudanalyzer-0.5.0/tests/test_image_evaluate.py +338 -0
  57. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_io.py +48 -1
  58. cloudanalyzer-0.5.0/tests/test_leaderboard.py +150 -0
  59. cloudanalyzer-0.5.0/tests/test_map_evaluate_core.py +206 -0
  60. cloudanalyzer-0.5.0/tests/test_mapeval_benchmark.py +36 -0
  61. cloudanalyzer-0.5.0/tests/test_mapeval_parity.py +72 -0
  62. cloudanalyzer-0.5.0/tests/test_phase35_map_metrics.py +86 -0
  63. cloudanalyzer-0.5.0/tests/test_plane_consistency.py +139 -0
  64. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_pr_comment.py +12 -16
  65. cloudanalyzer-0.5.0/tests/test_protocol.py +174 -0
  66. cloudanalyzer-0.5.0/tests/test_public_artifacts.py +70 -0
  67. cloudanalyzer-0.5.0/tests/test_rendered_evaluate.py +109 -0
  68. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_report.py +8 -0
  69. cloudanalyzer-0.5.0/tests/test_report_paths.py +49 -0
  70. cloudanalyzer-0.5.0/tests/test_slam_run_plugin_example.py +104 -0
  71. cloudanalyzer-0.5.0/tests/test_slam_run_registry.py +295 -0
  72. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_traj_batch.py +52 -0
  73. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_trajectory.py +87 -0
  74. cloudanalyzer-0.5.0/tests/test_uncertainty_evaluate.py +127 -0
  75. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_visualization.py +13 -0
  76. cloudanalyzer-0.4.0/ca/core/map_evaluate.py +0 -302
  77. cloudanalyzer-0.4.0/ca/io.py +0 -138
  78. cloudanalyzer-0.4.0/ca/visualization.py +0 -65
  79. cloudanalyzer-0.4.0/tests/test_map_evaluate_core.py +0 -81
  80. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/LICENSE +0 -0
  81. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/README.md +0 -0
  82. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/align.py +0 -0
  83. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/baseline_history.py +0 -0
  84. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/bundle.py +0 -0
  85. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/compare.py +0 -0
  86. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/convert.py +0 -0
  87. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/check_baseline_evolution.py +0 -0
  88. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/check_scaffolding.py +0 -0
  89. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/ground_evaluate.py +0 -0
  90. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/web_progressive_loading.py +0 -0
  91. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/web_sampling.py +0 -0
  92. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/core/web_trajectory_sampling.py +0 -0
  93. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/crop.py +0 -0
  94. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/density_map.py +0 -0
  95. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/detection.py +0 -0
  96. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/diff.py +0 -0
  97. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/downsample.py +0 -0
  98. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/evaluate.py +0 -0
  99. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/__init__.py +0 -0
  100. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/__init__.py +0 -0
  101. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/common.py +0 -0
  102. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/evaluate.py +0 -0
  103. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/pareto_promote.py +0 -0
  104. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/stability_window.py +0 -0
  105. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_baseline_evolution/threshold_guard.py +0 -0
  106. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/__init__.py +0 -0
  107. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/common.py +0 -0
  108. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/evaluate.py +0 -0
  109. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/literal_profiles.py +0 -0
  110. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/object_sections.py +0 -0
  111. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_scaffolding/pipeline_overlays.py +0 -0
  112. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/__init__.py +0 -0
  113. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/common.py +0 -0
  114. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/evaluate.py +0 -0
  115. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/pareto_frontier.py +0 -0
  116. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/severity_weighted.py +0 -0
  117. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/check_triage/signature_cluster.py +0 -0
  118. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/__init__.py +0 -0
  119. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/common.py +0 -0
  120. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/evaluate.py +0 -0
  121. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/height_band.py +0 -0
  122. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/nearest_neighbor.py +0 -0
  123. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/ground_evaluate/voxel_confusion.py +0 -0
  124. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/map_evaluate/__init__.py +0 -0
  125. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/map_evaluate/common.py +0 -0
  126. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/map_evaluate/evaluate.py +0 -0
  127. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/map_evaluate/nn_thresholds.py +0 -0
  128. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/map_evaluate/voxel_entropy.py +0 -0
  129. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/process_docs.py +0 -0
  130. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/__init__.py +0 -0
  131. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/common.py +0 -0
  132. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/evaluate.py +0 -0
  133. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/identity_passthrough.py +0 -0
  134. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/kiss_slam_driver.py +0 -0
  135. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/slam_run/small_gicp_driver.py +0 -0
  136. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/__init__.py +0 -0
  137. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/common.py +0 -0
  138. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/distance_shells.py +0 -0
  139. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/evaluate.py +0 -0
  140. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/grid_tiles.py +0 -0
  141. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_progressive_loading/spatial_shuffle.py +0 -0
  142. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/__init__.py +0 -0
  143. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/common.py +0 -0
  144. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/evaluate.py +0 -0
  145. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/functional_voxel.py +0 -0
  146. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/object_random.py +0 -0
  147. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_sampling/pipeline_hybrid.py +0 -0
  148. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/__init__.py +0 -0
  149. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/common.py +0 -0
  150. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/distance_accumulator.py +0 -0
  151. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/evaluate.py +0 -0
  152. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/turn_aware.py +0 -0
  153. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/experiments/web_trajectory_sampling/uniform_stride.py +0 -0
  154. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/filter.py +0 -0
  155. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/geometry.py +0 -0
  156. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/ground_evaluate.py +0 -0
  157. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/history.py +0 -0
  158. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/kitti.py +0 -0
  159. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/log.py +0 -0
  160. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/loop_closure_report.py +0 -0
  161. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/merge.py +0 -0
  162. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/metrics.py +0 -0
  163. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/mme.py +0 -0
  164. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/normals.py +0 -0
  165. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/pareto.py +0 -0
  166. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/pipeline.py +0 -0
  167. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/plot.py +0 -0
  168. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/point_summary.py +0 -0
  169. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/posegraph.py +0 -0
  170. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/registration.py +0 -0
  171. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/sample.py +0 -0
  172. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/scan_match_debug.py +0 -0
  173. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/slam_debug.py +0 -0
  174. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/split.py +0 -0
  175. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/stats.py +0 -0
  176. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/tracking.py +0 -0
  177. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/view.py +0 -0
  178. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/ca/web.py +0 -0
  179. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer.egg-info/dependency_links.txt +0 -0
  180. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer.egg-info/entry_points.txt +0 -0
  181. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer.egg-info/top_level.txt +0 -0
  182. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/cloudanalyzer_cli/__init__.py +0 -0
  183. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/setup.cfg +0 -0
  184. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/setup.py +0 -0
  185. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_align.py +0 -0
  186. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_baseline_history.py +0 -0
  187. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_batch.py +0 -0
  188. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_check_baseline_evolution_process.py +0 -0
  189. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_check_scaffolding_process.py +0 -0
  190. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_check_triage_process.py +0 -0
  191. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_compare.py +0 -0
  192. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_convert.py +0 -0
  193. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_crop.py +0 -0
  194. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_density_map.py +0 -0
  195. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_detection_evaluate.py +0 -0
  196. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_detection_tracking_report.py +0 -0
  197. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_diff.py +0 -0
  198. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_downsample.py +0 -0
  199. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_evaluate.py +0 -0
  200. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_filter.py +0 -0
  201. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_geometry_splat_ellipsoid.py +0 -0
  202. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_ground_evaluate.py +0 -0
  203. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_ground_evaluate_process.py +0 -0
  204. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_history.py +0 -0
  205. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_info.py +0 -0
  206. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_kitti.py +0 -0
  207. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_logging.py +0 -0
  208. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_loop_closure_report.py +0 -0
  209. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_map_evaluate.py +0 -0
  210. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_merge.py +0 -0
  211. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_metrics.py +0 -0
  212. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_mme.py +0 -0
  213. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_normals.py +0 -0
  214. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_object_eval_iou.py +0 -0
  215. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_output_json.py +0 -0
  216. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_pareto.py +0 -0
  217. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_phase16_large_scale.py +0 -0
  218. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_phase17_vectorize.py +0 -0
  219. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_phase18_vectorize.py +0 -0
  220. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_pipeline.py +0 -0
  221. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_plot.py +0 -0
  222. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_posegraph.py +0 -0
  223. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_process_docs.py +0 -0
  224. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_public_benchmark_pack.py +0 -0
  225. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_public_object_eval_examples.py +0 -0
  226. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_registration.py +0 -0
  227. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_run_batch.py +0 -0
  228. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_run_evaluate.py +0 -0
  229. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_sample.py +0 -0
  230. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_scan_match_debug.py +0 -0
  231. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_slam_debug.py +0 -0
  232. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_slam_run.py +0 -0
  233. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_split.py +0 -0
  234. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_stats.py +0 -0
  235. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_threshold.py +0 -0
  236. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_tracking_evaluate.py +0 -0
  237. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web.py +0 -0
  238. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_progressive_loading_core.py +0 -0
  239. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_progressive_loading_evaluate.py +0 -0
  240. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_progressive_loading_process.py +0 -0
  241. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_progressive_loading_strategies.py +0 -0
  242. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_sampling_core.py +0 -0
  243. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_sampling_evaluate.py +0 -0
  244. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_sampling_process.py +0 -0
  245. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_sampling_strategies.py +0 -0
  246. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_trajectory_sampling_core.py +0 -0
  247. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_trajectory_sampling_evaluate.py +0 -0
  248. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_trajectory_sampling_process.py +0 -0
  249. {cloudanalyzer-0.4.0 → cloudanalyzer-0.5.0}/tests/test_web_trajectory_sampling_strategies.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudanalyzer
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: CLI-first QA toolkit for point cloud, trajectory, and 3D perception outputs
5
5
  Author: rsasaki0109
6
6
  License-Expression: MIT
@@ -22,7 +22,7 @@ Classifier: Topic :: Scientific/Engineering :: Information Analysis
22
22
  Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: open3d>=0.17.0
25
+ Requires-Dist: open3d<0.20,>=0.17.0
26
26
  Requires-Dist: numpy>=1.24.0
27
27
  Requires-Dist: typer>=0.9.0
28
28
  Requires-Dist: matplotlib>=3.7.0
@@ -40,6 +40,17 @@ Provides-Extra: slam
40
40
  Requires-Dist: kiss-icp>=1.2.0; extra == "slam"
41
41
  Requires-Dist: kiss-slam>=0.0.2; extra == "slam"
42
42
  Requires-Dist: small_gicp>=1.0.0; extra == "slam"
43
+ Provides-Extra: ros
44
+ Requires-Dist: rosbags>=0.10; extra == "ros"
45
+ Provides-Extra: gs
46
+ Requires-Dist: torch>=2.0.0; extra == "gs"
47
+ Requires-Dist: gsplat>=1.0.0; extra == "gs"
48
+ Requires-Dist: lpips>=0.1.4; extra == "gs"
49
+ Requires-Dist: dreamsim>=0.2.1; extra == "gs"
50
+ Provides-Extra: perceptual
51
+ Requires-Dist: torch>=2.0.0; extra == "perceptual"
52
+ Requires-Dist: lpips>=0.1.4; extra == "perceptual"
53
+ Requires-Dist: dreamsim>=0.2.1; extra == "perceptual"
43
54
  Dynamic: license-file
44
55
 
45
56
  # CloudAnalyzer
@@ -1,3 +1,3 @@
1
1
  """CloudAnalyzer - AI-friendly CLI tool for point cloud analysis."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.5.0"
@@ -5,7 +5,6 @@ from pathlib import Path
5
5
 
6
6
  from ca.evaluate import evaluate
7
7
  from ca.io import SUPPORTED_EXTENSIONS, load_point_cloud
8
- from ca.info import get_info
9
8
  from ca.log import logger
10
9
  from ca.pareto import mark_quality_size_recommended
11
10
  from ca.trajectory import SUPPORTED_TRAJECTORY_EXTENSIONS, evaluate_trajectory
@@ -216,6 +215,8 @@ def batch_info(directory: str, recursive: bool = False) -> list[dict]:
216
215
  Returns:
217
216
  List of info dicts for each file found.
218
217
  """
218
+ from ca.info import get_info
219
+
219
220
  files = _find_point_cloud_files(directory, recursive=recursive)
220
221
  if not files:
221
222
  return []
@@ -331,8 +332,10 @@ def trajectory_batch_evaluate(
331
332
  align_rigid: bool = False,
332
333
  max_ate: float | None = None,
333
334
  max_rpe: float | None = None,
335
+ max_rpe_rotation_deg: float | None = None,
334
336
  max_drift: float | None = None,
335
337
  min_coverage: float | None = None,
338
+ rpe_distances_m: tuple[float, ...] | list[float] | None = None,
336
339
  ) -> list[dict]:
337
340
  """Evaluate all trajectory files in a directory against matched references."""
338
341
  files = _find_trajectory_files(directory, recursive=recursive)
@@ -367,8 +370,10 @@ def trajectory_batch_evaluate(
367
370
  align_rigid=align_rigid,
368
371
  max_ate=max_ate,
369
372
  max_rpe=max_rpe,
373
+ max_rpe_rotation_deg=max_rpe_rotation_deg,
370
374
  max_drift=max_drift,
371
375
  min_coverage=min_coverage,
376
+ rpe_distances_m=rpe_distances_m,
372
377
  )
373
378
  results.append(
374
379
  {
@@ -382,6 +387,9 @@ def trajectory_batch_evaluate(
382
387
  "coverage_ratio": eval_result["matching"]["coverage_ratio"],
383
388
  "ate": eval_result["ate"],
384
389
  "rpe_translation": eval_result["rpe_translation"],
390
+ "ate_rotation": eval_result["ate_rotation"],
391
+ "rpe_rotation": eval_result["rpe_rotation"],
392
+ "rpe_distance": eval_result["rpe_distance"],
385
393
  "drift": eval_result["drift"],
386
394
  "quality_gate": eval_result["quality_gate"],
387
395
  "inspect": _trajectory_inspection_commands(str(f), str(reference_path)),
@@ -36,12 +36,17 @@ All file paths in the manifest are resolved relative to the manifest file.
36
36
 
37
37
  from __future__ import annotations
38
38
 
39
+ import hashlib
40
+ import json
41
+ import platform
39
42
  from dataclasses import dataclass, field
40
43
  from pathlib import Path
41
44
  from typing import Any, Mapping
42
45
 
43
46
  import yaml # type: ignore[import-untyped]
44
47
 
48
+ import ca
49
+ from ca.report_paths import make_paths_portable
45
50
  from ca.run_evaluate import evaluate_run
46
51
 
47
52
 
@@ -50,10 +55,14 @@ GATE_KEYS: tuple[str, ...] = (
50
55
  "max_chamfer",
51
56
  "max_ate",
52
57
  "max_rpe",
58
+ "max_rpe_rotation_deg",
53
59
  "max_drift",
54
60
  "min_coverage",
55
61
  )
56
62
 
63
+ REPORT_BUNDLE_SCHEMA_VERSION = "cloudanalyzer.benchmark_report_bundle.v0.1"
64
+ METRICS_SCHEMA_VERSION = "cloudanalyzer.metrics.v1"
65
+
57
66
 
58
67
  @dataclass(frozen=True, slots=True)
59
68
  class BenchmarkSequence:
@@ -72,6 +81,7 @@ class BenchmarkSuite:
72
81
  description: str
73
82
  license: str | None
74
83
  source_path: Path
84
+ dataset: dict[str, Any] = field(default_factory=dict)
75
85
  sequences: dict[str, BenchmarkSequence] = field(default_factory=dict)
76
86
  gate: dict[str, float] = field(default_factory=dict)
77
87
 
@@ -205,6 +215,7 @@ def load_benchmark_suite(path: str | Path) -> BenchmarkSuite:
205
215
  )
206
216
 
207
217
  base_dir = manifest_path.parent
218
+ dataset = dict(_as_mapping(config.get("dataset"), "dataset"))
208
219
  sequences = _parse_sequences(
209
220
  config.get("sequences"),
210
221
  config.get("sample_outputs"),
@@ -220,6 +231,7 @@ def load_benchmark_suite(path: str | Path) -> BenchmarkSuite:
220
231
  sequences=sequences,
221
232
  gate=gate,
222
233
  source_path=manifest_path,
234
+ dataset=dataset,
223
235
  )
224
236
 
225
237
 
@@ -271,22 +283,268 @@ def evaluate_benchmark_run(
271
283
  max_time_delta=max_time_delta,
272
284
  align_origin=align_origin,
273
285
  align_rigid=align_rigid,
274
- **gate,
286
+ min_auc=gate.get("min_auc"),
287
+ max_chamfer=gate.get("max_chamfer"),
288
+ max_ate=gate.get("max_ate"),
289
+ max_rpe=gate.get("max_rpe"),
290
+ max_rpe_rotation_deg=gate.get("max_rpe_rotation_deg"),
291
+ max_drift=gate.get("max_drift"),
292
+ min_coverage=gate.get("min_coverage"),
275
293
  )
276
294
  result["benchmark"] = {
277
295
  "suite": suite.name,
278
296
  "version": suite.version,
279
297
  "sequence": seq.name,
280
298
  "source_path": str(suite.source_path),
299
+ "dataset": dict(suite.dataset),
281
300
  "gate": gate,
282
301
  "reference": {
283
302
  "map": str(seq.reference_map_path),
284
303
  "trajectory": str(seq.reference_trajectory_path),
285
304
  },
286
305
  }
306
+ result["schema_version"] = METRICS_SCHEMA_VERSION
307
+ result["runtime"] = {
308
+ "python": platform.python_version(),
309
+ "cloudanalyzer": getattr(ca, "__version__", "0.0.0"),
310
+ }
287
311
  return result
288
312
 
289
313
 
314
+ # ----------------------------------------------------------- report bundle
315
+
316
+
317
+ def _sha256_file(path: Path) -> str:
318
+ digest = hashlib.sha256()
319
+ with path.open("rb") as fp:
320
+ for chunk in iter(lambda: fp.read(1024 * 1024), b""):
321
+ digest.update(chunk)
322
+ return digest.hexdigest()
323
+
324
+
325
+ def _file_provenance(path: str | Path, roots: tuple[Path, ...]) -> dict[str, Any]:
326
+ resolved = Path(path).resolve()
327
+ portable_path = make_paths_portable(str(resolved), roots)
328
+ return {
329
+ "path": portable_path,
330
+ "sha256": _sha256_file(resolved),
331
+ "size_bytes": resolved.stat().st_size,
332
+ }
333
+
334
+
335
+ def _bundle_roots(
336
+ suite: BenchmarkSuite,
337
+ output_dir: Path,
338
+ extra_roots: tuple[Path | str, ...] = (),
339
+ ) -> tuple[Path, ...]:
340
+ roots: list[Path] = []
341
+ for candidate in (
342
+ Path.cwd(),
343
+ suite.source_path.parent,
344
+ output_dir.parent,
345
+ *extra_roots,
346
+ ):
347
+ path = Path(candidate).resolve()
348
+ if path not in roots:
349
+ roots.append(path)
350
+ return tuple(roots)
351
+
352
+
353
+ def _bundle_lock_payload(
354
+ *,
355
+ suite: BenchmarkSuite,
356
+ sequence: BenchmarkSequence,
357
+ result: Mapping[str, Any],
358
+ output_dir: Path,
359
+ map_path: str | Path,
360
+ trajectory_path: str | Path,
361
+ report_assets: list[str],
362
+ roots: tuple[Path, ...],
363
+ ) -> dict[str, Any]:
364
+ benchmark = result.get("benchmark")
365
+ benchmark_map = benchmark if isinstance(benchmark, Mapping) else {}
366
+ return {
367
+ "schema_version": REPORT_BUNDLE_SCHEMA_VERSION,
368
+ "metrics_schema_version": METRICS_SCHEMA_VERSION,
369
+ "suite": {
370
+ "name": suite.name,
371
+ "version": suite.version,
372
+ "description": suite.description,
373
+ "license": suite.license,
374
+ "dataset": dict(suite.dataset),
375
+ "sequence": sequence.name,
376
+ "source_path": make_paths_portable(str(suite.source_path), roots),
377
+ },
378
+ "gate": dict(benchmark_map.get("gate", suite.gate)),
379
+ "inputs": {
380
+ "candidate_map": _file_provenance(map_path, roots),
381
+ "candidate_trajectory": _file_provenance(trajectory_path, roots),
382
+ "reference_map": _file_provenance(sequence.reference_map_path, roots),
383
+ "reference_trajectory": _file_provenance(
384
+ sequence.reference_trajectory_path,
385
+ roots,
386
+ ),
387
+ "suite_manifest": _file_provenance(suite.source_path, roots),
388
+ },
389
+ "outputs": {
390
+ "metrics": "metrics.json",
391
+ "summary": "summary.md",
392
+ "report": "report.html",
393
+ "report_assets": report_assets,
394
+ "provenance": "provenance.json",
395
+ "manifest_lock": "manifest.lock.yaml",
396
+ },
397
+ "bundle_path": make_paths_portable(str(output_dir), roots),
398
+ }
399
+
400
+
401
+ def write_benchmark_report_bundle(
402
+ result: Mapping[str, Any],
403
+ suite: BenchmarkSuite,
404
+ output_dir: str | Path,
405
+ *,
406
+ map_path: str | Path,
407
+ trajectory_path: str | Path,
408
+ sequence: str | None = None,
409
+ extra_roots: tuple[Path | str, ...] = (),
410
+ ) -> dict[str, str]:
411
+ """Write the standard ``ca benchmark eval --out`` report bundle.
412
+
413
+ The bundle is a directory contract intended for CI artifacts and static
414
+ publishing. It is intentionally simple and inspectable:
415
+
416
+ - ``metrics.json``: portable benchmark result JSON
417
+ - ``summary.md``: PR-comment-ready Markdown summary
418
+ - ``report.html``: human report
419
+ - ``manifest.lock.yaml``: suite/gate/input hash lock
420
+ - ``provenance.json``: machine-readable bundle metadata
421
+ """
422
+ out = Path(output_dir)
423
+ out.mkdir(parents=True, exist_ok=True)
424
+ roots = _bundle_roots(suite, out.resolve(), extra_roots=extra_roots)
425
+ sequence_name = sequence
426
+ benchmark = result.get("benchmark")
427
+ if sequence_name is None and isinstance(benchmark, Mapping):
428
+ raw_sequence = benchmark.get("sequence")
429
+ if isinstance(raw_sequence, str):
430
+ sequence_name = raw_sequence
431
+ seq = suite.resolve_sequence(sequence_name)
432
+
433
+ portable_result = make_paths_portable(dict(result), roots)
434
+ metrics_path = out / "metrics.json"
435
+ metrics_path.write_text(
436
+ json.dumps(portable_result, indent=2),
437
+ encoding="utf-8",
438
+ )
439
+
440
+ from ca.pr_comment import build_pr_comment # local import avoids cold CLI cycles
441
+ from ca.report import save_run_report
442
+
443
+ summary_path = out / "summary.md"
444
+ summary_path.write_text(build_pr_comment(portable_result), encoding="utf-8")
445
+
446
+ report_path = out / "report.html"
447
+ save_run_report(portable_result, str(report_path))
448
+ report_assets = sorted(
449
+ path.name
450
+ for path in out.iterdir()
451
+ if path.is_file()
452
+ and path.name
453
+ not in {
454
+ "manifest.lock.yaml",
455
+ "metrics.json",
456
+ "provenance.json",
457
+ "report.html",
458
+ "summary.md",
459
+ }
460
+ )
461
+
462
+ lock_payload = _bundle_lock_payload(
463
+ suite=suite,
464
+ sequence=seq,
465
+ result=portable_result,
466
+ output_dir=out.resolve(),
467
+ map_path=map_path,
468
+ trajectory_path=trajectory_path,
469
+ report_assets=report_assets,
470
+ roots=roots,
471
+ )
472
+ manifest_lock_path = out / "manifest.lock.yaml"
473
+ manifest_lock_path.write_text(
474
+ yaml.safe_dump(lock_payload, sort_keys=False),
475
+ encoding="utf-8",
476
+ )
477
+
478
+ provenance = {
479
+ "schema_version": REPORT_BUNDLE_SCHEMA_VERSION,
480
+ "metrics_schema_version": METRICS_SCHEMA_VERSION,
481
+ "cloudanalyzer_version": getattr(ca, "__version__", "0.0.0"),
482
+ "summary_kind": "benchmark_run",
483
+ "benchmark": portable_result.get("benchmark"),
484
+ "overall_quality_gate": portable_result.get("overall_quality_gate"),
485
+ "artifacts": lock_payload["outputs"],
486
+ "inputs": lock_payload["inputs"],
487
+ }
488
+ provenance_path = out / "provenance.json"
489
+ provenance_path.write_text(
490
+ json.dumps(provenance, indent=2),
491
+ encoding="utf-8",
492
+ )
493
+
494
+ return {
495
+ "bundle_dir": str(out),
496
+ "metrics": str(metrics_path),
497
+ "summary": str(summary_path),
498
+ "report": str(report_path),
499
+ "manifest_lock": str(manifest_lock_path),
500
+ "provenance": str(provenance_path),
501
+ }
502
+
503
+
504
+ def validate_benchmark_report_bundle(output_dir: str | Path) -> dict[str, Any]:
505
+ """Validate the local shape of a benchmark report bundle.
506
+
507
+ This checks the machine-readable schema/version and referenced report
508
+ assets. It deliberately does not resolve portable input paths outside the
509
+ bundle; input hashes remain the authoritative provenance for that step.
510
+ """
511
+ root = Path(output_dir)
512
+ required = {
513
+ "metrics": root / "metrics.json",
514
+ "summary": root / "summary.md",
515
+ "report": root / "report.html",
516
+ "manifest_lock": root / "manifest.lock.yaml",
517
+ "provenance": root / "provenance.json",
518
+ }
519
+ missing = [name for name, path in required.items() if not path.is_file()]
520
+ if missing:
521
+ raise ValueError(f"Benchmark report bundle is missing: {', '.join(missing)}")
522
+
523
+ metrics = json.loads(required["metrics"].read_text(encoding="utf-8"))
524
+ provenance = json.loads(required["provenance"].read_text(encoding="utf-8"))
525
+ lock = yaml.safe_load(required["manifest_lock"].read_text(encoding="utf-8"))
526
+ if metrics.get("schema_version") != METRICS_SCHEMA_VERSION:
527
+ raise ValueError("metrics.json has an unsupported schema_version")
528
+ if provenance.get("metrics_schema_version") != METRICS_SCHEMA_VERSION:
529
+ raise ValueError("provenance.json has an unsupported metrics_schema_version")
530
+ if lock.get("schema_version") != REPORT_BUNDLE_SCHEMA_VERSION:
531
+ raise ValueError("manifest.lock.yaml has an unsupported schema_version")
532
+
533
+ report_assets = lock.get("outputs", {}).get("report_assets", [])
534
+ missing_assets = [name for name in report_assets if not (root / name).is_file()]
535
+ if missing_assets:
536
+ raise ValueError(
537
+ "Benchmark report bundle is missing report assets: "
538
+ + ", ".join(missing_assets)
539
+ )
540
+ return {
541
+ "valid": True,
542
+ "schema_version": REPORT_BUNDLE_SCHEMA_VERSION,
543
+ "metrics_schema_version": METRICS_SCHEMA_VERSION,
544
+ "report_assets": list(report_assets),
545
+ }
546
+
547
+
290
548
  # ----------------------------------------------------------- materialize
291
549
 
292
550
 
@@ -425,7 +683,11 @@ __all__: list[str] = [
425
683
  "BenchmarkSequence",
426
684
  "BenchmarkSuite",
427
685
  "GATE_KEYS",
686
+ "METRICS_SCHEMA_VERSION",
687
+ "REPORT_BUNDLE_SCHEMA_VERSION",
428
688
  "evaluate_benchmark_run",
429
689
  "load_benchmark_suite",
430
690
  "materialize_suite",
691
+ "write_benchmark_report_bundle",
692
+ "validate_benchmark_report_bundle",
431
693
  ]
@@ -33,6 +33,13 @@ from ca.core.check_triage import (
33
33
  rank_failed_checks,
34
34
  summarize_failed_checks,
35
35
  )
36
+ from ca.core.gate import (
37
+ GATE_SEVERITIES,
38
+ GATE_SUMMARY_SCHEMA_VERSION,
39
+ gate_status_for_check,
40
+ normalize_gate_severity,
41
+ summarize_gate_policy,
42
+ )
36
43
  from ca.core.ground_evaluate import (
37
44
  GroundEvaluateRequest,
38
45
  GroundEvaluateResult,
@@ -90,6 +97,8 @@ __all__ = [
90
97
  "GroundEvaluateRequest",
91
98
  "GroundEvaluateResult",
92
99
  "GroundEvaluateStrategy",
100
+ "GATE_SEVERITIES",
101
+ "GATE_SUMMARY_SCHEMA_VERSION",
93
102
  "DistanceShellsWebProgressiveLoadingStrategy",
94
103
  "RandomBudgetWebSamplingStrategy",
95
104
  "RankedCheckTriageItem",
@@ -114,7 +123,9 @@ __all__ = [
114
123
  "decide_baseline_evolution",
115
124
  "evaluate_ground",
116
125
  "failed_dimensions",
126
+ "gate_status_for_check",
117
127
  "load_check_suite",
128
+ "normalize_gate_severity",
118
129
  "normalized_dimension_gaps",
119
130
  "plan_progressive_loading_for_web",
120
131
  "rank_failed_checks",
@@ -126,4 +137,5 @@ __all__ = [
126
137
  "snapshot_margin_stats",
127
138
  "summarize_baseline_evolution",
128
139
  "summarize_failed_checks",
140
+ "summarize_gate_policy",
129
141
  ]