feat: preserve flatness suite measurement outputs

This commit is contained in:
2026-07-22 11:06:44 +08:00
parent 8555aa2f2e
commit 752ea3f944
9 changed files with 813 additions and 22 deletions

View File

@@ -322,6 +322,7 @@ class MeasurementPipeline:
excel_output_path: str | None = None,
result_template_path: str | Path | None = DEFAULT_RESULT_TEMPLATE,
combined_context_pointcloud_path: str | Path | None = DEFAULT_COMBINED_CONTEXT_POINTCLOUD,
save_combined_visualization: bool = True,
no_visualize: bool = False,
) -> dict[str, Any]:
batch_start_time = time.perf_counter()
@@ -443,7 +444,7 @@ class MeasurementPipeline:
combined_visualization_output = None
combined_pointclouds = []
if combined_visualizations:
if save_combined_visualization and combined_visualizations:
combined_visualization_output = self._contour_combined_save_path(save_path)
self._save_contour_combined_pointcloud_stream(
combined_visualizations,
@@ -627,6 +628,7 @@ class MeasurementPipeline:
template_sheet_name, headers, template_rows = self._read_measurement_template(template_path)
task_col = self._find_header_index(headers, ["任务号", "任务编号", "task_id"])
result_col = self._find_header_index(headers, ["测量结果"])
error_col = self._find_header_index(headers, ["误差结果"])
conclusion_col = self._find_header_index(headers, ["测量结论", "结论", "状态"])
result_by_task = {
@@ -648,6 +650,7 @@ class MeasurementPipeline:
continue
output_row[result_col] = self._row_measurement_mean(result_row)
output_row[error_col] = result_row.get("max")
output_row[conclusion_col] = self._row_measurement_conclusion(result_row)
table.append(output_row)
used_task_ids.add(task_id)
@@ -659,6 +662,7 @@ class MeasurementPipeline:
output_row = [""] * len(headers)
output_row[task_col] = task_id
output_row[result_col] = self._row_measurement_mean(result_row)
output_row[error_col] = result_row.get("max")
output_row[conclusion_col] = self._row_measurement_conclusion(result_row)
table.append(output_row)
@@ -729,7 +733,9 @@ class MeasurementPipeline:
def _row_measurement_conclusion(self, row: dict[str, Any]) -> str:
status = str(row.get("status", "")).strip()
if status and status != "成功":
if status in {"成功", "部分成功", "失败"}:
return status
if status:
return "失败"
value = self._row_measurement_mean(row)

View File

@@ -0,0 +1,62 @@
from pathlib import Path
from types import SimpleNamespace
from unittest import TestCase
from unittest.mock import Mock
import tempfile
import numpy as np
from pipeline import MeasurementPipeline
class CombinedContourRetentionTest(TestCase):
def make_pipeline(self, root: Path) -> MeasurementPipeline:
mesh = root / "mesh.ply"
pointcloud = root / "points.ply"
mesh.touch()
pointcloud.touch()
pipeline = MeasurementPipeline.__new__(MeasurementPipeline)
pipeline._resolve_contour_task_inputs = Mock(return_value=[{
"task_id": "1",
"sample_id": "sample",
"cad_path": None,
"mesh_path": mesh,
"pointcloud_path": pointcloud,
}])
pipeline._contour_task_save_path = Mock(return_value=root / "sample_contour.ply")
pipeline.run_contour = Mock(return_value={
"distance_stats": SimpleNamespace(max=0.5),
"distances": np.array([0.1, 0.2]),
"pointcloud": object(),
})
pipeline._contour_combined_save_path = Mock(return_value=root / "combined_contour.ply")
pipeline._save_contour_combined_pointcloud_stream = Mock()
pipeline._should_visualize = Mock(return_value=False)
return pipeline
def test_skips_combined_file_when_disabled(self) -> None:
with tempfile.TemporaryDirectory() as temp:
pipeline = self.make_pipeline(Path(temp))
result = pipeline.run_contour_batch(
all_tasks=True,
save_path=temp,
save_combined_visualization=False,
no_visualize=True,
)
self.assertIsNone(result["combined_visualization_output"])
pipeline._save_contour_combined_pointcloud_stream.assert_not_called()
def test_keeps_backward_compatible_combined_file_when_enabled(self) -> None:
with tempfile.TemporaryDirectory() as temp:
pipeline = self.make_pipeline(Path(temp))
result = pipeline.run_contour_batch(
all_tasks=True,
save_path=temp,
save_combined_visualization=True,
no_visualize=True,
)
self.assertEqual(result["combined_visualization_output"], Path(temp) / "combined_contour.ply")
pipeline._save_contour_combined_pointcloud_stream.assert_called_once()