from __future__ import annotations import unittest from pathlib import Path from app.simulation.reporting.amesim_results import load_test_mql_amesim_results from app.simulation.reporting.test_mql_comparison import compare_test_mql_series from app.simulation.reporting.test_mql_observations import build_test_mql_observation_catalog REPO_ROOT = Path(__file__).resolve().parents[1] TEST_MQL_AME = REPO_ROOT / "AmesimModels" / "test_mql.ame" class TestMqlObservationCatalogTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.amesim_results = load_test_mql_amesim_results(TEST_MQL_AME) cls.catalog = build_test_mql_observation_catalog(cls.amesim_results) def test_aggregates_observation_catalog_counts(self) -> None: self.assertEqual(len(self.catalog.chambers.bindings), 12) self.assertEqual(len(self.catalog.orifices.bindings), 16) self.assertEqual(self.catalog.lines.line_count, 40) self.assertEqual(self.catalog.mechanical.binding_count, 46) self.assertEqual(self.catalog.binding_count, 114) def test_reports_observed_data_paths_by_domain(self) -> None: paths_by_domain = self.catalog.data_paths_by_domain() self.assertEqual(set(paths_by_domain), {"chambers", "orifices", "lines", "mechanical"}) self.assertEqual(len(paths_by_domain["chambers"]), 100) self.assertEqual(len(paths_by_domain["orifices"]), 104) self.assertEqual(len(paths_by_domain["lines"]), 388) self.assertEqual(len(paths_by_domain["mechanical"]), 266) self.assertEqual(len(self.catalog.data_paths()), 858) self.assertIn("press@pn_general_chamber", paths_by_domain["chambers"]) self.assertIn("dm1@pn_orifice_18", paths_by_domain["orifices"]) self.assertIn("pctr@pneumatic_80", paths_by_domain["lines"]) self.assertIn("tforce@dynamic_mechanical_node_alternative_2", paths_by_domain["mechanical"]) def test_all_observed_data_paths_exist_in_saved_amesim_results(self) -> None: for data_path in self.catalog.data_paths(): with self.subTest(data_path=data_path): self.assertIn(data_path, self.amesim_results.series_by_data_path) def test_baseline_series_can_be_selected_for_comparison(self) -> None: selected_paths = ( "press@pn_general_chamber", "dm1@pn_orifice_18", "dm1@pneumatic_69", "vol1@pn_brp2_8", "tforce@dynamic_mechanical_node_alternative_2", ) baseline = self.catalog.baseline_series_by_data_path( self.amesim_results, selected_paths, ) self.assertEqual(tuple(baseline), selected_paths) self.assertEqual(len(baseline["press@pn_general_chamber"]), len(self.amesim_results.times)) self.assertAlmostEqual(baseline["vol1@pn_brp2_8"][-1], 34242.54636512914) def test_baseline_series_rejects_unobserved_data_path(self) -> None: with self.assertRaises(KeyError): self.catalog.baseline_series_by_data_path( self.amesim_results, ("not_a_real_signal@not_a_real_owner",), ) def test_observation_baseline_round_trips_through_comparison_with_zero_error(self) -> None: selected_paths = ( "press@pn_c1_8", "dm2@pn_morifice_11", "dmctr@pneumatic_75", "x1@mass_friction_endstops_10", ) baseline = self.catalog.baseline_series_by_data_path( self.amesim_results, selected_paths, ) comparison = compare_test_mql_series( python_times=self.amesim_results.times, python_series_by_data_path=baseline, amesim_results=self.amesim_results, data_paths=selected_paths, ) self.assertEqual(len(comparison.metrics), len(selected_paths)) self.assertEqual(comparison.max_abs_error, 0.0) self.assertEqual(comparison.max_rel_error, 0.0) if __name__ == "__main__": unittest.main()